帐户权限信息存放在mysql数据库中的user/db/host/tables_priv/columns_priv/procs_priv表中,在服务器启动时将其读入内存以供使用;
与oracle不同,mysql的帐户由用户名和主机名两部分组成,如不显示指定主机名则等同于’username’@’%’;
一个数据库会话从发起连接到执行sql,经历两个阶段的权限验证:数据库连接验证和sql请求验证
数据库连接验证
一个数据库连接由user表里的Host/user/password三个列进行验证,但user/password列都可能为空;
Mysql在服务器启动时将user表记录排序读入内存,当user表里有多条记录都匹配数据库连接时,则选择第一条;
排序规则:先排序host列,空值排在最后,%次之;然后是user列,空值排在最后
例1:
--user表原始记录
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-
读入内存排序后的记录
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-
这种规则可能会产生问题,即使客户端连接时显示指定了user名,也有可能最终以其他用户登陆进入mysql
例2
假定mysql服务器的localhost为thomas.loc.gov,从localhost以jeffrey为用户名尝试连接mysql
--user表记录
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| % | jeffrey | ...
| thomas.loc.gov | | ...
+----------------+----------+-
--内存排序后
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| thomas.loc.gov | | ...
| % | jeffrey | ...
+----------------+----------+-
则该连接会以anonymous匿名用户登录进入mysql
mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+
Sql请求验证
连接进入mysql服务器后,执行的每个sql都需要经过权限检查,相关表为user/db/host/tables_priv/columns_priv/procs_priv
user表是全局性的,比如user表赋给一个用户delete权限,则该用户可以删除任何表的记录;所以最好只赋给管理员用户;
db/host则是数据库级别的,两表的host/db列均可使用通配符;对于db表,其host列若为%则表示所有主机,为空则需联系host表进一步查看;对于host表,%或空值代表所有主机;对两表而言,db列为%或空值代表所有数据库;
db/host表同user表一起在服务器启动时读入内存并排序,db表基于host/db/user列,而host表则基于host/db列;当有多行匹配时以第一行为准;
另外三个表从其名称即可看出其适用范围,只有host列可以使用通配符%或_;
每当服务器接受到请求时,便查询这7个表以验证其权限;
当收到管理员命令诸如shutdown/reload时,只查询user表;
当收到数据库相关请求insert/update时,首先检查user表,没有相应global权限时再去检查db/host表;检查db表的host/user/db列,如无返回行则请求被拒绝,若返回行的host列为空,则需进一步查找host表验证,若host表有返回行则交集匹配,即两个表的权限列都须为Y(此功能允许将数据库操作权限只赋给特定host发起的用户连接)
用户权限计算规则类似下面的表达式
global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
OR routine privileges
注:
Grant/revoke操作不会对host表产生影响,但可以用来维护特定的安全server列表,反之亦然;
比如,假定公共网络的public.your.domain不完全,可通过如下设置来自禁止该域名的机器访问
+--------------------+----+-
| Host | Db | ...
+--------------------+----+-
| public.your.domain | % | ... (all privileges set to 'N')
| %.your.domain | % | ... (all privileges set to 'Y')
+--------------------+----+-
如何使修改的权限生效
如果通过调用grant/revoke/set password/rename user等命令修改权限,则服务器会立即刷新并将grant表重新载入内存;
若通过insert/update/delete直接修改grant表,则需要手工重载这些表(flush privileges/mysqladmin flush-privileges/mysqladmin reload),否则只有在服务器重启后才能生效;
修改权限并重载grant表,会对现有的连接产生如下影响:
表/列权限改动会在客户端下一次请求时生效;数据库权限改动在客户端下次执行use db_name时生效;global权限和密码只对新发起的连接生效;
当服务器使用—skip-grant-tables启动时,则不会读取grant表,任何用户都可以登录并进行任何操作
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15480802/viewspace-751456/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/15480802/viewspace-751456/