{
...
}
vio_keepalive(net->vio, TRUE);
...
char *user= end;
char *passwd= strend(user)+1;
uint user_len= passwd - user - 1;
char *db= passwd;
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
uint dummy_errors;
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION
(uchar)(*passwd++) : strlen(passwd);
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB
db + passwd_len + 1 : 0;
uint db_len= db strlen(db) : 0;
if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
{
inc_host_errors(&thd->remote.sin_addr);
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
return 1;
}
...
/* If username starts and ends in "'", chop them off */
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
{
user[user_len-1]= 0;
user++;
user_len-= 2;
}
if (thd->main_security_ctx.user)
x_free(thd->main_security_ctx.user);
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
return 1; /* The error is set by my_strdup(). */
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);//验证用户名和密码
}
上面的源码主要做了如下几件事情:
获取客户端的IP和主机名
acl_check_host函数验证USER表中是否存在相应的IP或HOST,如果不存在直接报错
获取用户名和密码
check_user函数验证用户名和密码(不输入用户名默认为ODBC),如果系统表中不存在匹配的报错返回
获取用户的权限列表,验证用户的相关属性是否合法,如连接数是否超过上限,连接是否超时,操作是否超过限制等信息,如果不合法,则报错返回。
由于在一个认证的过程中涉及到的东西比较多,各个方面吧,我不能一一跟踪,只能大概了解其中的实现流程,捡重点进行
跟踪,有兴趣的童鞋自己具体跟踪吧
题外话:
Mysql中权限系统表都是在系统启动时,载入内存的(当然User表也是这样),一般情况下,不需要进行频繁的授权和回收
操作,这中情况下,权限表基本保持不变,将其在系统启动的时候载入内存的好处自然是快速的进行权限判断,减少磁盘的I/O,
你懂的^_^。有好处自然有坏处,就是在频繁进行授权和回收相关操作时,权限表需要重新载入内存,Mysql为了避免这种情况,
在手册中已经说的很清楚了,授权和回收只会反应到磁盘中,内存的数据字典信息是不会改变的,如果想立即生效,需要调用
FLUSH PRIVILEGES系统函数,这个系统函数的工作应该就是对权限系统表的RELOAD。
下篇进入实质性的介绍,通过跟踪一个建表语句,来学习Mysql是如何存储表的元数据的,即frm格式文件的剖析。
<script>
PS.最近工作比较清闲,却迷失了方向,一会想看OS的实现,一会想看逆向,一会又想看计算机组成原理,哎,转专业的学生伤
不起啊,计算机很神奇,我很迷茫…
摘自 心中无码