MySQL用户与权限
PS:本文是对mysql5.7.32撰写的文档!!!
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.32 |
+-----------+
1 row in set (0.00 sec)
一、知识概述
PS:一个小时内用户查询或者连接数量超过资源控制限制,用户将被锁定,直到下一个小时,才可以在此执行对应的操作。但是可以使用 GRANT语句更新这些字段的值。
1.用户列
user表的用户列包括 Host、 User、password(在5.7.32中password叫authentication_string),分别表示主机名、用户名和密码。其中 user和 Host为user表的联合主踺。当用户与服务器之间建立连接时,输入的账户信息中的用户名称、主机名和密码必须匹配user表中对应的字段,只有3个值都匹配的时候,才允许连接的建立。这3 个字段的值就是创建账户时保存的账户信息。修改用户密码时,实际就是修改user表的password字段的值。
2.权限列
权限列的字段决定了用户的权限,描述了在全局范围内允许对数据和数据库进行的操作。包括查询权限、修改权限等普通权限,还包括了关闭服务器、超级权限和加载用户等高级权限。普通权限用于操作数据库;高级权限用于数据库管理。 user表中对应的权限是针对所有用户数据库的。这些字段值的类型为 ENUM,可以取的值只能为 Y和 N, Y表示该用户有对应的权限; N表示用户没有对应的权限。查看user表的结构可以看到,这些字段的值默认都是 N。如果要修改权限,可以使用 GRANT语句或 UPDATE语句更改 user表的这些字段来修改用户对应的权限。
3.安全列
安全列只有6个字段,其中两个是 SSI相关的,2个是 x509相关的,另外2个是授权插件相关的。SSI用于加密; X509标准可用于标识用户: Plugin字段标识可以用于验证用户身份的插件,如果该字段为空,服务器使用内建授权验证机制验证用户身份。可以通过 SHOW VARIABLES LIKE ’ have_openssl’语句来查询服务器是否支持 SSI功能。
4.资源控制列
资源控制列的字段用来限制用户使用的资源,包含4个字段,分别为:
- Max_questions—用户每小时允许执行的查询操作次数。
- Max_updates一用户每小时允许执行的更新操作次数。
- Max_connections—用户每小时允许执行的连接操作次数。
- Max_user_connections—用户允许同时建立的连接次数。
5.Db表和Host表
db表和 host表是 MYSQL数据中非常重要的权限表。 db表中存储了用户对某个数据库的操作权限,决定用户能从哪个主机存取哪个数据库。 host表中存储了某个主机对数据库的操作权限,配合db权限表对给定主机上数据库级操作权限做更细致的控制。这个权限表不受 GRANT和 REVOKE语句的影响。 db表比较常用, host表一般很少使用。 db表和 host表结构相似,字段大致可以分为两类:用户列和权限列
二、创建用户
语法:
mysql> help create user
Name: 'CREATE USER'
Description:
Syntax:
CREATE USER [IF NOT EXISTS]
user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...
......
- User:表示创建的用户的名称;
- host:表示允许登陆的用户主机名称;
- IDENTIFIED BY:表示用来设置用户的密码;
- [PASSWORD] :表示使用哈希值设置密码;
- ‘password’:表示用户登陆时使用的普通明文密码;
- IDENTIFIED WITH:表示用户指定一个身份验证插件;
- auth_plugin:是插件的名称;
- ‘auth_string’:是可选的字符串,解释插件的意义。 查看MySQL的用户
方法一:使用CREATE USER语句创建新用户
#带密码创建
mysql> create user 'tom'@'localhost' identified by '123.com';
Query OK, 0 rows affected (0.10 sec)
#不带密码创建
mysql> create user 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.00 sec)
#利用哈希加密创建用户
mysql> select password('123.com');
+-------------------------------------------+
| password('123.com') |
+-------------------------------------------+
| *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
+-------------------------------------------+
1 row in set, 1 warning (0.04 sec)
mysql> create user 'wangwu'@'localhost' identified by password '*AC241830FFDDC8943AB311CBD47D758E79F7953EA';
Query OK, 0 rows affected, 1 warning (0.00 sec)
#查询mysql库user表中User字段为tom的列
mysql> select * from mysql.user where user='tom'\G;
*************************** 1. row ***************************
Host: localhost
User: tom
#以下是权限,“N”表示没有对应的权限,“Y”表示拥有对应的权限-
Select_priv: N
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: *AC241830FFDDC8943AB31CBD47D758E79F7953EA #经过哈希加密过的密码
password_expired: N
password_last_changed: 2021-01-05 15:05:20
password_lifetime: NULL
account_locked: N
1 row in set (0.10 sec)
ERROR:
No query specified
方法二:使用Grant语句创建新用户
#创建用户lisi
mysql> grant select,update on *.* to 'lisi'@'localhost' identified by '123.com';
Query OK, 0 rows affected, 1 warning (0.01 sec)
#查询mysql库user表中User字段为lisi的列:以下是权限,“N”表示没有对应的权限,“Y”表示拥有对应的权限-
mysql> select host,user,select_priv,update_priv from mysql.user where user='lisi';
+-----------+------+-------------+-------------+
| host | user | select_priv | update_priv |
+-----------+------+-------------+-------------+
| localhost | lisi | Y | Y |
+-----------+------+-------------+-------------+
1 row in set (0.00 sec)
#新添加的用户还无法使用账号和密码登陆MySQL,需要使用FLUSH告诉服务器重新加载授权
mysql> FLUSH privileges;
Query OK, 0 rows affected (0.00 sec)
拓展:验证创建的用户是否有对应的权限
#用lisi用户登录
[root@mysql ~]# mysql -ulisi -p123.com
#查看有哪些数据库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
#查看test数据库
mysql> show tables from test;
+----------------+
| Tables_in_test |
+----------------+
| test |
+----------------+
1 row in set (0.00 sec)
#查看test库下test表
mysql> select * from test.test;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | a | 100 |
| 2 | b | 100 |
+------+------+------+
2 rows in set (0.00 sec)
#更新数据
mysql> update test.test set c=1000 where a=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#查看更新数据
mysql> select * from test.test;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | a | 1000 |
| 2 | b | 100 |
+------+------+------+
2 rows in set (0.00 sec)
**总结:**lisi用户之所以能够查看到的原因是因为在创建lisi用户的时候给予了select和update权限!!!
三、删除用户
1.使用DROP USER语句删除
mysql> drop user zhangsan@localhost;
Query OK, 0 rows affected (0.00 sec)
2.使用DELETE语句删除用户
#查看mysql中user表有哪些用户!!!
mysql> SELECT host,user,authentication_string FROM mysql.user;
+-----------+---------------+-------------------------------------------+
| host | user | authentication_string |
+-----------+---------------+-------------------------------------------+
| localhost | root | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| localhost | mysql.session | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | mysql.sys | *THISISNOTAVALIDPASSWORDTHATCANBEUSEDHERE |
| localhost | tom | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
| localhost | zhangsan | |
| localhost | wangwu | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
| localhost | lisi | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
| localhost | testUser | *AC241830FFDDC8943AB31CBD47D758E79F7953EA |
+-----------+---------------+-------------------------------------------+
8 rows in set (0.01 sec)
#删除
mysql> delete from mysql.user where host='localhost' and user ='tom';
Query OK, 1 row affected (0.32 sec)
四、修改用户
1.Root用户修改自己的密码
1.1 使用mysqladmin命令
[root@mysql ~]# mysqladmin -u root -p password "123.com"
Enter password: #填写root用户旧密码
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
1.2 修改mysql数据库的user表
mysql> update mysql.user set authentication_string=password("123456") where user="root" and host="localhost";
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 1
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
1.3 使用SET语句修改root用户的密码
mysql> SET PASSWORD=PASSWORD("123.com");
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
2.Root用户修改普通用户密码
2.1 使用SET语句来修改普通用户的密码
mysql> SET PASSWORD FOR 'testUser'@'localhost'=PASSWORD("newped");
Query OK, 0 rows affected, 1 warning (0.00 sec)
2.2 使用UPDATE语句修改普通用户密码
mysql> UPDATE mysql.user SET authentication_string=password("mima") where user='testUser' and host='localhost';
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 1
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
2.3 使用GRANT语句修改普通用户密码
mysql> GRANT USAGE ON *.* TO 'testUser'@'localhost' IDENTIFIED BY '123.com';
Query OK, 0 rows affected, 1 warning (0.00 sec)
3.普通用户修改自己的密码
#普通用户修改密码 先登录
[root@mysql ~]# mysql -utestUser -p123.com
#修改密码
mysql> SET PASSWORD=PASSWORD("newped");
Query OK, 0 rows affected, 1 warning (0.00 sec)
#退出
mysql> exit
Bye
#使用新密码登录
[root@mysql ~]# mysql -utestUser -pnewped
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 16
Server version: 5.7.32 Source distribution
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
4…Root用户密码丢失的解决办法
3.1使用–skip-grant-tables选项启动mysql服务
[root@mysql ~]# systemctl stop mysqld.service
[root@mysql ~]# mysqld -uroot --skip-grant-tables
#无密码可登录
[root@mysql ~]# mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.32 Source distribution
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
#更加mysql.user修改密码
mysql> update mysql.user set authentication_string=password('123') where user='root' and host='localhost';
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 1
#刷新一下
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
#重启mysql服务,使用新密码登录
[root@mysql ~]# systemctl restart mysqld
[root@mysql ~]# mysql -uroot -p123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.32 Source distribution
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
五、权限管理
权限管理主要是对登陆到MySQL的用户进行权限验证。所有用户的权限都存储在MySQL的权限表中,不合理的权限规划给MySQL服务器带来安全隐患。MySQL权限系统的主要功能是证实连接到一台给定主机的用户,并赋予该用户在数据库上SELECT\INSERT\UPDATE和DELETE权限。账户权限信息被存储在MySQL数据库的user、db、tables_priv、columns_priv和procs_priv表中。在MySQL启动时,服务器将这些数据库表中权限信息的内容读入内存。
权限
- CREATE和 DROP权限,可以创建新数据库和表,或删除(移掉)己有数据库和表。如果将 MySQL数据库中的 DROP权限授予某用户,用户可以删掉 MySQL访问权限保存的数据库。
- SELECT、 INSERT、 UPDATE和DELETE权限允许在一个数据库现有的表上实施操作。
- SELECT权限只有在它们真正从一个表中检索行时才被用到。
- INDEX权限允许创建或删除索引, INDEX适用己有表。如果具有某个表的 CREATE权限,可以在CREATE TABLE语句中包括索引定义。
- ALTER权限,可以使用 ALTER TABLE来更改表的结构和重新命名表。
- CREATE ROUTINE权限来创建保存的程序(函数和程序), ALTER ROUTINE权限用来更改和删除保存的程序, EXECUTE权限用来执行保存的程序。
- RANT权限允许授权给其他用户。可用于数据库、表和保存的程序。
- FILE权限给予用户使用 LOAD DATA INFILE和 SELECT… INTO OUTFILE语句读或写服务器上的文件,任何被授予 FILE权限的用户都能读或写 MySQL服务器上的任何文件。(说明用户可以读任何数据库目录下的文件,因为服务器可以访问这些文件)。 FILE权限允许用户在 MySQL服务器具有写权限的目录下创建新文件,但不能覆盖己有文件。
授权
授权就是为某个用户授予权限。合理的授权可以保证数据库的安全。MySQL中可以使用GRANT语句为用户授予权限。 授予的权限可以分为多个层级:
- 全局层级 全局权限适用于一个给定服务器中的所有数据库。这些权限存储在mysql.user表中。GRANT ALL ON 和REVOKE ALL ON 只授予和撤销全局权限。
- 数据库层级 数据库权限适用于一个给定数据库中的所有目标。这些权限存储在mysql.db 和mysql.host 表中。GRANT ALL ON db_name 和 REVOKE ALL ON db_name.* 只授予和撤销数据库权限。
- 表层级 表权限适用于一个给定表中的所有列。这些权限存储在mysql.tables_priv表中。GRANT ALL ON db_name.tb1_name 和 REVOKE ALL ON db_name.tb1_name只授予和撤销表权限。
- 列层级 列权限适用于一个给定表中的单一列。这些权限存储在mysql.columns_priv表中。当使用REVOKE时,必须指定与被授权列相同的列。
- 子程序层级 CREATE ROUTINE、 ALTER ROUTINE、 EXCUTE和 GRANT权限适用于己存储的子程序。这些权限可以被授予为全局层级和数据库层级。而且,除了CREATE ROUTINE外,这些权限可以被授予子程序层级,并存储在 mysql.procs_priv表中。 在 MySQL中,必须是拥有 GRANT权限的用户才可以执行 GRANT语句。要使用 GRANT或 REVOKE,必须拥有 GRANT OPTION权限,并且必须用于正在授予或撤销的权限。
GRANT的语法如下:
mysql> help grant
Name: 'GRANT'
Description:
Syntax:
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH {GRANT OPTION | resource_option} ...]
GRANT PROXY ON user
TO user [, user] ...
[WITH GRANT OPTION]
object_type: {
TABLE
| FUNCTION
| PROCEDURE
}
priv_level: {
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
user:
(see https://dev.mysql.com/doc/refman/5.7/en/account-names.html)
- Privileges:表示赋予用户的权限类型;
- db.table:表示用户的权限所作用的数据库中的表;
- identified by关键字用来设置密码;
- ‘password’用户的密码; [with grant option]可选项,表示对新建立的用户赋予GRANT权限。
GRANT OPTION的取值有5个,意义:
- GRANT OPTION:将自己的权限赋予其他的用户。
- |MAX_QUERIES_PER_HOUR count:设置每个小时可以执行count次查询
- |MAX_UPDATE_PER_HOUR count:设置每个小时可以执行count次更新
- |MAX_CONNECTIONS_PER_HOUR count:设置每个小时可以建立count个连接
- |MAX_USER_PER_HOUR count:设置单个用户可以同时建立count个连接 创建权限并查看
创建权限
mysql> GRANT SELECT,INSERT ON *.* TO 'masan'@'localhost' IDENTIFIED BY 'grantpwd';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> SELECT Host,User,Select_priv,Insert_priv,Grant_priv from mysql.user where user='masan';
+-----------+-------+-------------+-------------+------------+
| Host | User | Select_priv | Insert_priv | Grant_priv |
+-----------+-------+-------------+-------------+------------+
| localhost | masan | Y | Y | N |
+-----------+-------+-------------+-------------+------------+
1 row in set (0.01 sec)
收回权限
收回权限就是取消已经赋予用户的某些权限。收回用户不必要的权限可以在一定程度上保证系统的安全性。MySQL中使用REVOKE语句取消用户的某些权限,使用REVOKE收回权限之后,用户账号的记录将从db,host,user,tables_priv和columns_priv表中删除,但是用户账号记录仍然在user表中保存(删除user表中的账户记录,用DROP USER语句) REVOKE语句有两种用法,第一种语法是收回所有用户的所有权限,此语法用于取消对已命名的用户的所有全局层级,数据库层级,表层级和列层级的权限。
mysql> REVOKE INSERT ON *.* FROM 'masan'@'localhost';
Query OK, 0 rows affected (0.00 sec)
#查看用户权限
mysql> SELECT Host,User,Select_priv,Insert_priv,Grant_priv from mysql.user where user='masan';
+-----------+-------+-------------+-------------+------------+
| Host | User | Select_priv | Insert_priv | Grant_priv |
+-----------+-------+-------------+-------------+------------+
| localhost | masan | Y | N | N |
+-----------+-------+-------------+-------------+------------+
1 row in set (0.00 sec)
mysql> SHOW GRANTS FOR 'masan'@'localhost'\G
*************************** 1. row ***************************
Grants for masan@localhost: GRANT SELECT ON *.* TO 'masan'@'localhost'
1 row in set (0.00 sec)