MySQL访问控制实现原理
MySQL访问控制实现原理
MySQL 访问控制实际上由两个功能模块共同组成,从第一篇的第二章架构组成中可以看
到,一个是负责 “看守 MySQL 大门”的用户管理模块,另一个就是负责监控来访者每一个动
作的访问控制模块。用户管理模块决定造访客人能否进门,而访问控制模块则决定每个客人
进门能拿什么不能拿什么。下面是一张 MySQL 中实现访问控制的简单流程图(见图 4-2):
1、 用户管理
我们先看看用户管理模块是如何工作的。在 MySQL 中,用户访问控制部分的实现比较简
单,所有授权用户都存放在一个系统表中: mysql.user,当然这个表不仅仅存放了授权用户
的基本信息,还存放有部分细化的权限信息。用户管理模块需要使用的信息很少,主要就是
Host,User,Password 这三项,都在 mysql.user 表中,如下:
sky@localhost : (none) 12:35:04> USE mysql;
Database changed
sky@localhost : mysql 12:35:08> DESC user;
+---------------+--------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------------+------+-----+---------+-------+
| Host | char(60) | NO | PRI | | |
| User | char(16) | NO | PRI | | |
| Password | char(41) | NO | | | |
... ...
+---------------+--------------------+------+-----+---------+-------+
一个用户要想访问 MySQL,至少需要提供上面列出的这三项数据,MySQL 才能判断是否
该让他 “进门”。这三项实际上由量部分组成:访问者来源的主机名(或者主机 IP 地址信息 )
和访问者的来访 “暗号”(登录用户名和登录密码),这两部分中的任何一个没有能够匹配上
都无法让看守大门的用户管理模块乖乖开门。其中 Host 信息存放的是 MySQL 允许所对应的
User 的信任主机,可以是某个具体的主机名(如: mytest)或域名(如:www.domain.com),
也可以是以“%”来充当通配符的某个域名集合(如:%.domain.com);也可以是一个具体的
IP 地址(如:1.2.3.4),同样也可以是存在通配符的域名集合(如:1.2.3.%);还可以用“%”
来代表任何主机,就是不对访问者的主机做任何限制。如以下设置:
root@localhost : mysql 01:18:12> SELECT host,user,password FROM user ORDER BY
user;
+--------------------+------+-------------------------------------------+
| host | user | password |
+--------------------+------+-------------------------------------------+
| % | abc | |
| *.jianzhaoyang.com | abc | |
| localhost | abc | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| 1.2.3.4 | abc | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| 1.2.3.* | def | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| % | def | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
| localhost | def | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
... ...
+--------------------+------+-------------------------------------------+
但是这里有一个比较特殊的访问限制,如果要通过 localhost 访问的话,必须要有一条
专门针对 localhost 的授权信息,即使不对任何主机做限制也不行。如下例所示,存在 def@%
的用户设置,但是如果不使用-h 参数来访问,则登录会被拒绝,因为 mysql 在默认情况下
会连接 localhost:
sky@sky:~$ mysql -u def -p
Enter password:
ERROR 1045 (28000): Access denied for user 'def'@'localhost' (using
password: YES)
但是当通过-h 参数,明确指定了访问的主机地址之后就没问题了,如下:
sky@sky:~$ mysql -u def -p -h 127.0.0.1
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 5.0.51a-log Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
def@127.0.0.1 : (none) 01:26:04>
如果我们有一条 localhost 的访问授权则可以不使用-h 参数来指定登录 host 而连接默
认的 localhost:
sky@sky:~$ mysql -u abc -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.0.51a-log Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
abc@localhost : (none) 01:27:19> exit
Bye
如果 MySQL 正在运行之中的时候,我们对系统做了权限调整,那调整之后的权限什么时
候会生效呢?
我们先了解何时 MySQL 存放于内存结构中的权限信息被更新:FLUSH PRIVILEGES 会强
行让 MySQL 更新 Load 到内存中的权限信息; GRANT、REVOKE 或者 CREATE USER 和 DROP USER
操作会直接更新内存中俄权限信息;重启 MySQL 会让 MySQL 完全从 grant tables 中读取权
限信息。
那内存结构中的权限信息更新之后对已经连接上的用户何时生效呢?
对于 Global Level 的权限信息的修改,仅仅只有更改之后新建连接才会用到,对于已
经连接上的 session 并不会受到影响。而对于 Database Level 的权限信息的修改,只有当
客户端请求执行了“USE database_name”命令之后,才会在重新校验中使用到新的权限信
息。所以有些时候如果在做了比较紧急的 Global 和 Database 这两个 Level 的权限变更之后 ,
可能需要通过“KILL”命令将已经连接在 MySQL 中的 session 杀掉强迫他们重新连接以使
用更新后的权限。对于 Table Level 和 Column Level 的权限,则会在下一次需要使用到该
权限的 Query 被请求的时候生效,也就是说,对于应用来讲,这两个 Level 的权限,更新之
后立刻就生效了,而不会需要执行“KILL”命令。
2、 访问控制
当客户端连接通过用户管理模块的验证,可连接上 MySQL Server 之后,就会发送各种
Query 和 Command 给 MySQL Server,以实现客户端应用的各种功能。当 MySQL 接收到客户
端的请求之后,访问控制模块是需要校验该用户是否满足提交的请求所需要的权限。权限校
验过程是从最大范围的权限往最小范围的权限开始依次校验所涉及到的每个对象的每个权
限。
在验证所有所需权限的时候, MySQL 首先会查找存储在内存结构中的权限数据,首先查
找 Global Level 权限,如果所需权限在 Global Level 都有定义(GRANT 或者 REVOKE),
则完成权限校验(通过或者拒绝),如果没有找到所有权限的定义,则会继续往后查找
Database Level 权限,进行 Global Level 未定义的所需权限的校验,如果仍然没有能够
找到所有所需权限的定义,MySQL 会继续往更小范围的权限定义域查找,也就是 Table
Level,最后则是 Column Level 或者 Routine Level。
下面我们就以客户端通过 abc@localhost 连接后请求如下 Query 我为例:
SELECT id,name FROM test.t4 where status = 'deleted';
在前面我们了解到 MySQL 的 grant tables 有 mysql.user,mysql.db,mysql.host,
mysql.table_priv 和 mysql.column_priv 这五个,我想出了 mysql.host 之外的四个都是非
常容易理解的,每一个表针对 MySQL 中的一种逻辑对象,存放某一特定 Level 的权限,唯独
mysql.host 稍有区别。我们现在就来看看 mysql.host 权限表到底在 MySQL 的访问控制中充
当了一个什么样的角色呢?
mysql.host 在 MySQL 访问控制模块中所实现的功能比较特殊,和其他几个 grant tables
不太一样。首先是 mysql.host 中的权限数据不是(也不能)通过 GRANT 或者 REVOKE 来授予
或者去除,必须通过手工通过 INSERT、UPDATE 和 DELETE 命令来修改其中的数据。其次是
其中的权限数据无法单独生效,必须通过和 mysql.db 权限表的数据一起才能生效。而且仅
当 mysql.db 中存在不完整(某些场景下的特殊设置)的时候,才会促使访问控制模块再结
合 mysql.host 中查找是否有相应的补充权限数据实现以达到权限校验的目的,就比如上图
中所示。在 mysql.db 中无法找到满足权限校验的所有条件的数据(db.User = 'abc' AND
db.host = 'localhost' AND db.Database_name = 'test'),则说明在 mysql.db 中无法完
成权限校验,所以也不会直接就校验 db.Select_priv 的值是否为'Y'。但是 mysql.db 中有
db.User = 'abc' AND db.Database_name = 'test' AND db.host = '' 这样一条权限信息
存在,大家可能注意到了这条权限信息中的 db.host 中是空值,注意是空值而不是'%'这个
通配符哦。当 MySQL 注意到有这样一条权限信息存在的时候,就该是 mysql.host 中所存放
的权限信息出场的时候了。这时候,MySQL 会检测 mysql.host 中是否存在满足如下条件的
权限信息:host.Host = 'localhost' AND host.Db = 'test'。如果存在,则开始进行
Select_priv 权限的校验。由于权限信息存在于 mysql.db 和 mysql.host 两者之中,而且是
两者信息合并才能满足要求,所以 Select_priv 的校验也需要两表都为'Y'才能满足要求,
通过校验。
我们已经清楚,MySQL 的权限是授予“username@hostname”的,也就是说,至少需要
用户名和主机名二者才能确定一个访问者的权限。又由于 hostname 可以是一个含有通配符
的域名,也可以是一个含有通配符的 IP 地址段。那么如果同一个用户有两条权限信息,一
条是针对特定域名的,另外一个是含有通配符的域名,而且前者属于后者包含。这时候 MySQL
如何来确定权限信息呢?实际上 MySQL 永远优先考虑更精确范围的权限。在 MySQL 内部会按
照 username 和 hostname 作一个排序,对于相同 username 的权限,其 host 信息越接近访问
者的来源 host,则排序位置越靠前,则越早被校验使用到。而且, MySQL 在权限校验过程中 ,
只要找到匹配的权限之后,就不会再继续往后查找是否还有匹配的权限信息,而直接完成校
验过程。
大家应该也看到了在 mysql.user 这个权限表中有 max_questions,max_updates,
max_connections,max_user_connections 这四列,前面三列是从 MySQL4.0.2 版本才开始
有的,其功能是对访问用户进行每小时所使用资源的限制,而最后的 max_user_connections
则是从 MySQL5.0.3 版本才开始有的,他和 max_connections 的区别是限制耽搁用户的连接
总次数,而不是每小时的连接次数。而要使这四项限制生效,需要在创建用户或者给用户授
权的时候加上以下四种子句:
max_questions : WITH MAX_QUERIES_PER_HOUR n;
max_updates : WITH MAX_UPDATES_PER_HOUR n;
max_connections : WITH MAX_CONNECTIONS_PER_HOUR n;
max_user_connections: MAX_USER_CONNECTIONS。
四个子句可以同时使用,如:
“ WITH MAX_QUERIES_PER_HOUR 5000 MAX_CONNECTIONS_PER_HOUR 10
MAX_USER_CONNECTIONS 10000”。
MySQL访问控制实现原理的更多相关文章
- MYSQL索引结构原理、性能分析与优化
[转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...
- MySQL主从同步原理 部署【转】
一.主从的作用:1.可以当做一种备份方式2.用来实现读写分离,缓解一个数据库的压力二.MySQL主从备份原理master 上提供binlog ,slave 通过 I/O线程从 master拿取 bin ...
- MySQL InnoDB 索引原理
本文由 网易云发布. 作者:范鹏程,网易考拉海购 InnoDB是 MySQL最常用的存储引擎,了解InnoDB存储引擎的索引对于日常工作有很大的益处,索引的存在便是为了加速数据库行记录的检索.以下是 ...
- 你的MySQL服务器开启SSL了吗?SSL在https和MySQL中的原理思考
最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主 ...
- 数据库MySQL 之 索引原理与慢查询优化
数据库MySQL 之 索引原理与慢查询优化 浏览目录 索引介绍方法类型 聚合索引辅助索引 测试索引 正确使用索引 组合索引 注意事项 查询计划 慢查询日志 大数据量分页优化 一.索引介绍方法类型 1. ...
- MySQL主从复制异步原理以及搭建
MySQL主从复制的原理: 1.首先,MySQL主库在事务提交时会把数据变更作为时间events记录在二进制日志文件binlog中:MySQL主库上的sync_binlog参数控制Binlog日志以什 ...
- MySQL Optimization 优化原理
MySQL Optimization 优化原理 MySQL逻辑架构 如果能在头脑中构建一幅MySQL各组件之间如何协同工作的架构图,有助于深入理解MySQL服务器.下图展示了MySQL的逻辑架构图. ...
- MySql 缓存查询原理与缓存监控 和 索引监控
MySql缓存查询原理与缓存监控 And 索引监控 by:授客 QQ:1033553122 查询缓存 1.查询缓存操作原理 mysql执行查询语句之前,把查询语句同查询缓存中的语句进行比较,且是按字节 ...
- MySQL 储存过程-原理、语法、函数详细说明
Mysql储存过程是一组为了完成特定功能的SQL语句集,经过编译之后存储在数据库中,当需要使用该组SQL语句时用户只需要通过指定储存过程的名字并给定参数就可以调用执行它了,简而言之就是一组已经写好的命 ...
随机推荐
- 浅谈mmap()和ioremap()的用法与区别
一.mmap()mmap()函数是用来将设备内存线性地址映射到用户地址空间.(1)首先映射基地址,再通过偏移地址寻址:(2)unsigned char *map_cru_base=(unsigned ...
- SYRefresh 一款简洁易用的刷新控件 支持tableview,collectionview水平垂直刷新功能
SYRefresh 地址: https://github.com/shushaoyong/SYRefresh 一款简洁易用的刷新控件 示例程序: 默认刷新控件使用方法: //添加头部刷新控件 Sc ...
- hexo从零开始到搭建完整
前言 其实平时自己写的文章并不多,偶尔看到一些东西会做点笔记,但是每次写的东西都会到处放,不好找,所以才想着自己搭建一个人博客网站,现在大家用hexo比较多,也比较方便,并且能使用的主题也很多,所以小 ...
- ArrayList源码解析(二)自动扩容机制与add操作
本篇主要分析ArrayList的自动扩容机制,add和remove的相关方法. 作为一个list,add和remove操作自然是必须的. 前面说过,ArrayList底层是使用Object数组实现的. ...
- WCF(远程服务器返回错误: 400 错误的请求)
类似相关问题有以下: WCF- restful接口 POST方式调用报错(远程服务器返回错误: 400 错误的请求) WCF Rest:不使用UriTemplate使用post方式传参解决HTTP40 ...
- SmartCoder每日站立会议05
1.站立会议内容 经过四天的努力,我们的微信小程序有了很大的进展,首页的设计定了方案,API接地图正在试着把消息展示到其中,争取把地图信息做到直观形象. 站立会议照片: 2.任务展板 3.燃尽图
- 《实战java高并发程序设计》源码整理及读书笔记
日常啰嗦 不要被标题吓到,虽然书籍是<实战java高并发程序设计>,但是这篇文章不会讲高并发.线程安全.锁啊这些比较恼人的知识点,甚至都不会谈相关的技术,只是写一写本人的一点读书感受,顺便 ...
- css reset的重置作用(可取还是不可取,取决于你)
一.重置的理由 当今流行的浏览器中,有些都是以自己的方式去理解css规范,这就会到只有的浏览器对css的解释与设计师的css定义初衷相冲突,使得网页的样子在某些浏览器下能正确按照设计师的想法显示.,但 ...
- ATmega8仿真——外部中断的学习
前面我们学习了ATmega8的I/O口作为通用数字输入/输出口来用时对LED数码管控制和扫描按键的应用: 但ATmega8多数的I/O口都是复用口,除了作为通用数字I/O使用,还有其第二功能,这里我们 ...
- makefile介绍1.0
1.gcc参数 -o指定生成文件名 -c只编译不链接 2.makefile标准格式 CC=gcc #编译器变量,#代表注释 SRCS=main.cpp\#源文件变量 a.cpp\ b.cpp\ c.c ...