MySQL用户账户管理和权限管理深入讲解
前言
mysql 的权限表在数据库启动的时候就载入内存,当用户通过身份认证后,就在内存中进行相应权限的存取,这样,此用户就可以在数据库中做权限范围内的各种操作了。
下面话不多说了,来一起看看详细的介绍吧
mysql 的权限体系大致分为5个层级:
全局层级
全局权限适用于一个给定服务器中的所有数据库。这些权限存储在mysql.user表中。grant all on *.*和revoke all on *.*只授予和撤销全局权限。
数据库层级
数据库权限适用于一个给定数据库中的所有目标。这些权限存储在mysql.db和mysql.host表中。grant all on db_name.*和revoke all on db_name.*只授予和撤销数据库权限。
表层级
表权限适用于一个给定表中的所有列。这些权限存储在mysql.talbes_priv表中。grant all on db_name.tbl_name和revoke all on db_name.tbl_name只授予和撤销表权限。
列层级
列权限适用于一个给定表中的单一列。这些权限存储在mysql.columns_priv表中。当使用revoke时,您必须指定与被授权列相同的列。
子程序层级
create routine, alter routine, execute和grant权限适用于已存储的子程序。这些权限可以被授予为全局层级和数据库层级。而且,除了create routine外,这些权限可以被授予为子程序层级,并存储在mysql.procs_priv表中。
这些权限信息存储在下面的系统表中:
mysql.user
mysql.db
mysql.host
mysql.table_priv
mysql.column_priv
当用户连接进来,mysqld会通过上面的这些表对用户权限进行验证!
一、权限表的存取
在权限存取的两个过程中,系统会用到 “mysql” 数据库(安装 mysql 时被创建,数据库名称叫“mysql”) 中 user、host 和 db 这3个最重要的权限表。
在这 3 个表中,最重要的表示 user 表,其次是 db 表,host 表在大多数情况下并不使用。
user 中的列主要分为 4 个部分:用户列、权限列、安全列和资源控制列。
通常用的最多的是用户列和权限列,其中权限列又分为普通权限和管理权限。普通权限用于数据库的操作,比如 select_priv、super_priv 等。
当用户进行连接时,权限表的存取过程有以下两个过程:
先从 user 表中的 host、user 和 password 这 3 个字段中判断连接的 ip、用户名、和密码是否存在于表中,如果存在,则通过身份验证,否则拒绝连接。
如果通过身份验证、则按照以下权限表的顺序得到数据库权限:user -> db -> tables_priv -> columns_priv。
在这几个权限表中,权限范围依次递减,全局权限覆盖局部权限。上面的第一阶段好理解,下面以一个例子来详细解释一下第二阶段。
为了方便测试,需要修改变量 sql_mode,不然会报错,如下
mysql [(none)]> grant select on *.* to xxx@localhost; error 1133 (42000): can't find any matching row in the user table mysql [(none)]> set session sql_mode='strict_trans_tables,no_engine_substitution'; query ok, 0 rows affected, 2 warnings (0.07 sec) mysql [(none)]> grant select on *.* to xxx@localhost; query ok, 0 rows affected, 2 warnings (0.10 sec)
// sql_mode 默认值中有 no_auto_create_user (防止grant自动创建新用户,除非还指定了密码) set session sql_mode='strict_trans_tables,no_engine_substitution';
1. 创建用户
xxx@localhost,并赋予所有数据库上的所有表的 select 权限
先查看user表显示的权限状态
mysql [mysql]> select * from user where user="xxx" and host='localhost' \g; *************************** 1. row *************************** host: localhost user: xxx select_priv: y insert_priv: n update_priv: n delete_priv: n create_priv: n drop_priv: n reload_priv: n shutdown_priv: n process_priv: n file_priv: n grant_priv: n references_priv: n index_priv: n alter_priv: n show_db_priv: n super_priv: n create_tmp_table_priv: n lock_tables_priv: n execute_priv: n repl_slave_priv: n repl_client_priv: n create_view_priv: n show_view_priv: n create_routine_priv: n alter_routine_priv: n create_user_priv: n event_priv: n trigger_priv: n create_tablespace_priv: n ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 0 max_user_connections: 0 plugin: mysql_native_password authentication_string: password_expired: n password_last_changed: 2018-12-03 17:34:49 password_lifetime: null account_locked: n
再查看db表的权限状态
mysql [mysql]> select * from db where user="xxx" and host='localhost' \g; empty set (0.03 sec)
可以发现user表中select_priv: y,其他均为n
db表中则无记录
也就是说,对所有数据库都具有相同的权限的用户并不需要记录到 db 表,而仅仅需要将 user 表中的 select_priv 改为 “y” 即可。换句话说,user 表中的每个权限都代表了对所有数据库都有权限。
2. 将 xxx@localhost 上的权限改为只对 db1 数据库上所有表的 select 权限。
mysql [mysql]> create database db1; query ok, 1 row affected (0.01 sec) mysql [mysql]> re^c mysql [mysql]> revoke select on *.* from xxx@localhost; query ok, 0 rows affected, 1 warning (0.06 sec) mysql [mysql]> grant select on db1.* to xxx@localhost; query ok, 0 rows affected, 1 warning (0.09 sec) mysql [mysql]> select * from user where user='xxx'\g; *************************** 1. row *************************** host: localhost user: xxx select_priv: n insert_priv: n update_priv: n delete_priv: n create_priv: n drop_priv: n reload_priv: n
mysql [mysql]> select * from db where user='xxx'\g; *************************** 1. row *************************** host: localhost db: db1 user: xxx select_priv: y insert_priv: n update_priv: n delete_priv: n create_priv: n drop_priv: n grant_priv: n references_priv: n index_priv: n alter_priv: n create_tmp_table_priv: n lock_tables_priv: n create_view_priv: n show_view_priv: n create_routine_priv: n alter_routine_priv: n execute_priv: n event_priv: n trigger_priv: n
这时候发现,user 表中的 select_priv 变为 “n” ,而 db 表中增加了 db 为 xxx 的一条记录。也就是说,当只授予部分数据库某些权限时,user 表中的相应权限列保持 “n”,而将具体的数据库权限写入 db 表。table 和 column 的权限机制和 db 类似。
3. tables_priv记录表权限
mysql [db1]> create table t1(id int(10),name char(10)); query ok, 0 rows affected (0.83 sec) mysql [db1]> grant select on db1.t1 to mmm@localhost; query ok, 0 rows affected, 2 warnings (0.06 sec) mysql [mysql]> select * from user where user='mmm'\g; *************************** 1. row *************************** host: localhost user: mmm select_priv: n insert_priv: n update_priv: n delete_priv: n create_priv: n drop_priv: n reload_priv: n ... mysql [mysql]> select * from db where user='mmm'\g; empty set (0.00 sec) mysql [mysql]> select * from tables_priv where user='mmm'\g; *************************** 1. row *************************** host: localhost db: db1 user: mmm table_name: t1 grantor: root@localhost timestamp: 0000-00-00 00:00:00 table_priv: select column_priv: 1 row in set (0.00 sec) error: no query specified mysql [mysql]> select * from columns_priv where user='mmm'\g; empty set (0.00 sec)
可以看见tables_priv表中增加了一条记录,而在user db columns_priv三个表中没有记录
从上例可以看出,当用户通过权限认证,进行权限分配时,将按照 ==user -> db -> tables_priv -> columns_priv== 的顺序进行权限分配,即先检查全局权限表 user,如果 user 中对应 权限为 “y”,则此用户对所有数据库的权限都为“y”,将不再检查 db、tables_priv 和 columns_priv;如果为“n”,则到 db 表中检查此用户对应的具体数据库,并得到 db 中为 “y”的权限;如果 db 中相应权限为 “n”,则再依次检查tables_priv 和 columns_priv 中的权限,如果所有的都为“n”,则判断为不具备权限。
二. 账户管理
授权 grant
grant不仅可以用来授权,还可以用来创建用户。
授权的语法:
grant 权限列表 on 库名.表名 to 用户@主机 identified by '密码';
创建用户 p1 ,权限为可以在所有数据库上执行所有权限,只能从本地进行连接
mysql [mysql]> grant all privileges on *.* to p1@localhost; query ok, 0 rows affected, 2 warnings (0.03 sec) mysql [mysql]> select * from user where user='p1'\g *************************** 1. row *************************** host: localhost user: p1 select_priv: y insert_priv: y update_priv: y delete_priv: y create_priv: y drop_priv: y reload_priv: y shutdown_priv: y process_priv: y file_priv: y grant_priv: n references_priv: y index_priv: y alter_priv: y show_db_priv: y super_priv: y create_tmp_table_priv: y lock_tables_priv: y execute_priv: y repl_slave_priv: y repl_client_priv: y create_view_priv: y show_view_priv: y create_routine_priv: y alter_routine_priv: y create_user_priv: y event_priv: y trigger_priv: y create_tablespace_priv: y ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 0 max_user_connections: 0 plugin: mysql_native_password authentication_string: password_expired: n password_last_changed: 2018-12-03 18:11:01 password_lifetime: null account_locked: n 1 row in set (0.00 sec)
除了 grant_priv 权限外,所有权限在user 表里面都是 “y”。
增加对 p1 的 grant 权限
mysql [mysql]> grant all privileges on *.* to p1@localhost with grant option; query ok, 0 rows affected, 1 warning (0.03 sec) mysql [mysql]> select * from user where user='p1'\g *************************** 1. row *************************** host: localhost user: p1 select_priv: y insert_priv: y update_priv: y delete_priv: y create_priv: y drop_priv: y reload_priv: y shutdown_priv: y process_priv: y file_priv: y grant_priv: y references_priv: y index_priv: y alter_priv: y show_db_priv: y super_priv: y create_tmp_table_priv: y lock_tables_priv: y execute_priv: y repl_slave_priv: y repl_client_priv: y create_view_priv: y show_view_priv: y create_routine_priv: y alter_routine_priv: y create_user_priv: y event_priv: y trigger_priv: y create_tablespace_priv: y ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 0 max_user_connections: 0 plugin: mysql_native_password authentication_string: password_expired: n password_last_changed: 2018-12-03 18:11:01 password_lifetime: null account_locked: n 1 row in set (0.00 sec)
设置密码赋予grant权限
mysql [mysql]> grant all privileges on *.* to p1@localhost identified by '123' with grant option; query ok, 0 rows affected, 2 warnings (0.01 sec) mysql [mysql]> select * from user where user='p1'\g *************************** 1. row *************************** host: localhost user: p1 select_priv: y insert_priv: y update_priv: y delete_priv: y create_priv: y drop_priv: y reload_priv: y shutdown_priv: y process_priv: y file_priv: y grant_priv: y references_priv: y index_priv: y alter_priv: y show_db_priv: y super_priv: y create_tmp_table_priv: y lock_tables_priv: y execute_priv: y repl_slave_priv: y repl_client_priv: y create_view_priv: y show_view_priv: y create_routine_priv: y alter_routine_priv: y create_user_priv: y event_priv: y trigger_priv: y create_tablespace_priv: y ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 0 max_user_connections: 0 plugin: mysql_native_password authentication_string: *23ae809ddacaf96af0fd78ed04b6a265e05aa257 password_expired: n password_last_changed: 2018-12-03 18:14:40 password_lifetime: null account_locked: n 1 row in set (0.00 sec)
在5.7版本后的数据库,密码字段改为authentication_string
创建新用户 p2,可以从任何 ip 连接,权限为对 db1 数据库里的所有表进行 select 、update、insert 和 delete 操作,初始密码为“123”
mysql [mysql]> grant select,insert,update,delete on db1.* to 'p2'@'%' identified by '123'; query ok, 0 rows affected, 1 warning (0.01 sec) mysql [mysql]> select * from user where user='p2'\g; *************************** 1. row *************************** host: % user: p2 select_priv: n insert_priv: n update_priv: n delete_priv: n create_priv: n drop_priv: n reload_priv: n shutdown_priv: n ... create_tablespace_priv: n ssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0 max_updates: 0 max_connections: 0 max_user_connections: 0 plugin: mysql_native_password authentication_string: *23ae809ddacaf96af0fd78ed04b6a265e05aa257 password_expired: n password_last_changed: 2018-12-03 18:20:44 password_lifetime: null account_locked: n 1 row in set (0.00 sec) error: no query specified mysql [mysql]> select * from db where user='p2'\g; *************************** 1. row *************************** host: % db: db1 user: p2 select_priv: y insert_priv: y update_priv: y delete_priv: y create_priv: n drop_priv: n grant_priv: n references_priv: n index_priv: n alter_priv: n create_tmp_table_priv: n lock_tables_priv: n create_view_priv: n show_view_priv: n create_routine_priv: n alter_routine_priv: n execute_priv: n event_priv: n trigger_priv: n 1 row in set (0.00 sec)
user 表中的权限都是“n”,db 表中增加的记录权限则都是“y”,这样只授予用户适当的权限,而不会授予过多的权限。
本例中的 ip 限制为所有 ip 都可以连接,因此设置为 “%”,mysql 数据库中是通过 user 表的 host 字段来进行控制,host 可以是以下类型的赋值。
注意: mysql 数据库的 user 表中 host 的值为 “%” 或者空,表示所有外部 ip 都可以连接,但是不包括本地服务器 localhost,因此,如果要包括本地服务器,必须单独为 localhost 赋予权限。
授予 super、process、file 权限给用户 p3@%
mysql [mysql]> grant super,process,file on db1.* to 'p3'@'%'; error 1221 (hy000): incorrect usage of db grant and global privileges mysql [mysql]> grant super,process,file on *.* to 'p3'@'%'; query ok, 0 rows affected (0.03 sec)
这几个权限都是属于管理权限,因此不能够指定某个数据库,on 后面必须跟 *.*,否则会提示错误,如上
那这几个权限是干啥的?
process通过这个权限,用户可以执行show processlist和kill命令。默认情况下,每个用户都可以执行show processlist命令,但是只能查询本用户的进程。
拥有file权限才可以执行 select ..into outfile和load data infile…操作,但是不要把file, process, super权限授予管理员以外的账号,这样存在严重的安全隐患。
super这个权限允许用户终止任何查询;修改全局变量的set语句;使用change master,purge master logs
另外一个比较特殊的
usage权限
连接(登陆)权限,建立一个用户,就会自动授予其usage权限(默认授予)。
该权限只能用于数据库登陆,不能执行任何操作;且usage权限不能被回收,也即``revoke用户并不能删除用户。
查看账号权限
账号创建好后,可以通过如下命令查看权限:
show grants for user@host; mysql [mysql]> show grants for p2@'%'; +-------------------------------------------------------------+ | grants for p2@% | +-------------------------------------------------------------+ | grant usage on *.* to 'p2'@'%' | | grant select, insert, update, delete on `db1`.* to 'p2'@'%' | +-------------------------------------------------------------+ 2 rows in set (0.00 sec)
更改账户权限
创建用户账号p4,权限为对db1所有表具有select权限
mysql [mysql]> grant select on db1.* to p4@'%'; query ok, 0 rows affected, 1 warning (0.01 sec) mysql [mysql]> show grants for p4@'%'; +-------------------------------------+ | grants for p4@% | +-------------------------------------+ | grant usage on *.* to 'p4'@'%' | | grant select on `db1`.* to 'p4'@'%' | +-------------------------------------+ 2 rows in set (0.00 sec)
增加delete权限
mysql [mysql]> grant delete on db1.* to p4@'%'; query ok, 0 rows affected (0.01 sec) mysql [mysql]> show grants for p4@'%'; +---------------------------------------------+ | grants for p4@% | +---------------------------------------------+ | grant usage on *.* to 'p4'@'%' | | grant select, delete on `db1`.* to 'p4'@'%' | +---------------------------------------------+ 2 rows in set (0.00 sec)
和已有的 select 权限进行合并
删除delete权限
revoke 语句可以回收已经赋予的权限
mysql [mysql]> show grants for p4@'%'; +---------------------------------------------+ | grants for p4@% | +---------------------------------------------+ | grant usage on *.* to 'p4'@'%' | | grant select, delete on `db1`.* to 'p4'@'%' | +---------------------------------------------+ 2 rows in set (0.00 sec) mysql [mysql]> revoke delete on db1.* from p4@'%'; query ok, 0 rows affected (0.01 sec) mysql [mysql]> show grants for p4@'%'; +-------------------------------------+ | grants for p4@% | +-------------------------------------+ | grant usage on *.* to 'p4'@'%' | | grant select on `db1`.* to 'p4'@'%' | +-------------------------------------+ 2 rows in set (0.00 sec)
usage能revoke?
mysql [mysql]> revoke select on db1.* from p4@'%'; query ok, 0 rows affected (0.02 sec) mysql [mysql]> show grants for p4@'%'; +--------------------------------+ | grants for p4@% | +--------------------------------+ | grant usage on *.* to 'p4'@'%' | +--------------------------------+ 1 row in set (0.00 sec) mysql [mysql]> revoke usage on db1.* from p4@'%'; error 1141 (42000): there is no such grant defined for user 'p4' on host '%'
usage 权限不能被回收,也就是说,revoke 用户并不能删除用户。
要彻底的删除账号,可以使用 drop user
drop user p4@'%';
账号资源限制
创建 mysql 账号时,还有一类选项称为账号资源限制,这类选项的作用是限制每个账号实际具有的资源限制,这里的“资源”主要包括:
max_queries_per_hour count : 单个账号每小时执行的查询次数
max_upodates_per_hour count : 单个账号每小时执行的更新次数
max_connections_per_hour count : 单个账号每小时连接服务器的次数
max_user_connections count : 单个账号并发连接服务器的次数
注意:
添加用户或者权限,使用mysql> flush privileges; 刷新权限
具体权限可以参考官网文档
https://dev.mysql.com/doc/refman/5.7/en/privileges-provided.html
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
上一篇: C#实现远程关闭计算机或重启计算机的方法
下一篇: C#实现简单的Login窗口实例