开门见山
前文讲述了MySQL用户管理之认证,当某客户端成功认证,接下来的操作就需要进行权限验证,如验证用户的select、insert、update等操作权限,shutdown、process、file等管理权限等。
MySQL授权杂货
授权层级
MySQL支持global、database、table、column等不同层级授权。同时,还可以对用户的routine(procedures & functions)等权限进行控制,具体控制项可以查看mysql.user表的列信息。如下:
管理权限
MySQL的主要管理选项有:FILE、PROCESS:、SUPER、ALL等。
FILE:允许用户读写服务器上的文件;
PROCESS:允许用户执行show PROCESSLIST命令查看所有连接的客户端;
SUPER: 允许用户kill掉其他客户端的连接;
ALL:允许所有权限, 除了给其他用户授权;
注意:
给其他用户授权的权限,需要在对此用户本身授权时加上WITH GRANT OPTION子句。如下,笔者用debian-sys-maint用户登录(密码在/etc/mysql/debian.cnf文件中,root用户本身没有grant权限),并创建一个super用户,赋予WITH GRANT OPTION选项。后面就可以用super给其他用户授权了。
- root用户给test1用户授权,失败---因为root用户本身没有grant权限;
- debian-sys-maint给super用户授权,成功;
- 用super用户再次给test1用户授权—成功。
GRANT授权
MySQL使用grant语句为用户授权,格式如下:
GRANT XXX1 ON database.XXX2 TO 'user'@'hostname' [ with grant option ]
其中:
- XXX1标识具体权限,如select、insert、all privileges等,多个权限项用,分割,如下:
mysql> grant all privileges on *.* TO 'test1'@'%' WITH GRANT OPTION;
Query OK, 0 rows affected (0.16 sec)
- with grant option表示传递grant 授权,带此子句后,被授权的user可以进一步为其他用户授权相关权限;
显示用户的grant权限
- 显示当前用户的grant权限
mysql> show grants;
+----------------------------------------------------------------------+
| Grants for super@localhost |
+----------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'super'@'localhost' WITH GRANT OPTION |
+----------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> show grants for current_user();
+----------------------------------------------------------------------+
| Grants for super@localhost |
+----------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'super'@'localhost' WITH GRANT OPTION |
+----------------------------------------------------------------------+
1 row in set (0.00 sec)
- 显示指定用户权限
mysql> show grants for 'common'@'%';
+---------------------------------------------------------------+
| Grants for common@% |
+---------------------------------------------------------------+
| GRANT SELECT, INSERT ON *.* TO 'common'@'%' WITH GRANT OPTION |
+---------------------------------------------------------------+
1 row in set (0.00 sec)
Grant Tables权限元数据表
MySQL使用特定的表存储权限相关的信息,即metadata。除了我们熟知的mysql.user表外,还有:db、tables_priv、columns_priv、procs_priv等;如
- mysql.sys用户对sys数据库拥有权限;
- tables_priv表记录用户对表的权限;
FLUSH PRIVILEGES语句
我们在MySQL系列:9 存储引擎中已经知道,表是存储在表空间(文件)中的。mysqld在启动时将权限相关表读入到内存中,以免频繁磁盘访问开销。当我们使用类似update、insert直接修改表时,其内存副本并不生效。因而需要FLUSH PRIVILEGES语句指示mysqld重新加载权限表。
- 关于skip-grant-tables选项的详细解释:
上篇博文中提到,若忘记mysql登录密码,可以使用skip-grant-tables选项重启服务进程,然后免密登录修改指定用户密码。但是修改之前需要先FLUSH PRIVILEGES重新加载权限表。原因就是因为skip-grant-tables选项启动mysqld进程时,内存中根本没有选项表的数据,所以无法更改。
- 权限表内存副本自动刷新条件
使用create user、grant、revoke等子句修改相关用户权限时,MySQL自动刷新内存副本(具体不同MySQL版本略有不同),因为当使用alter命令修改权限时,需要flush才能生效。
回收账户权限
可使用revoke XXX from命令回收账户权限,如下:
mysql> show grants for 'common'@'%' ;
+---------------------------------------------------------------+
| Grants for common@% |
+---------------------------------------------------------------+
| GRANT SELECT, INSERT ON *.* TO 'common'@'%' WITH GRANT OPTION |
+---------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> revoke INSERT ON *.* from 'common'@'%';
Query OK, 0 rows affected (0.03 sec)
mysql> show grants for 'common'@'%' ;
+-------------------------------------------------------+
| Grants for common@% |
+-------------------------------------------------------+
| GRANT SELECT ON *.* TO 'common'@'%' WITH GRANT OPTION |
+-------------------------------------------------------+
1 row in set (0.00 sec)
SHOW PROCESSLIST
此命令显示所有已连接的客户线程ID(并不是整个mysqld守护进程的所有线程)和正在执行的命令,mysql对每个连接创建一个线程(thread_handling选项,one-thread-per-connection)。如下:
mysql> SHOW PROCESSLIST;
+----+-------+-----------+------+---------+------+----------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+------+---------+------+----------+------------------+
| 11 | super | localhost | NULL | Query | 0 | starting | SHOW PROCESSLIST |
| 12 | root | localhost | NULL | Sleep | 6 | | NULL |
+----+-------+-----------+------+---------+------+----------+------------------+
2 rows in set (0.00 sec)
设置账户资源限制
mysql.user表的最后记录是关于资源限制的信息,如可以设置同一用户的同时连接数。如下:
说明:
- 首先用alter user 'common'@'%' with MAX_USER_CONNECTIONS 1;设置最大用户连接数为1;
- 同时开两个窗口进行链接,第二次链接会报连接超限。第一次链接已成功(show processlist)。
总结
如上两篇博文详细的介绍了MySQL的认证/授权机制,针对不同的MySQL版本,其控制细节略有差异。读者在实际应用中,应根据具体场景、具体版本合理的设置应用用户的权限,以实现MySQL数据库安全稳定的运行。