前言
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
在学习这一章节的时候,我们可以先了解一下【数据库原理 • 五】数据库安全性与完整性的定义
和【数据库原理 • 三】关系数据库标准语言SQL的概念和发展历史
mysql用户权限原理和实战
- 一、访问控制
- 1.1 连接验证(阶段1)
- 1.2 允许的连接
- 1.3 连接的优先级
- 1.4 请求验证(阶段二)
- 二、用户管理
- 2.1 新增用户
- 2.2 用户修改
- 2.2.1 使用alter修改用户
- 2.2.2 DML语句管理mysql用户
- 2.3 删除用户
- 2.4 查看用户
- 2.4.1 show create user 显示用户非权限属性
- 2.4.2 select from mysql.user 查看已经创建的用户
- 2.4.3 select current_user() 查看当前登录用户
- 三、密码管理
- 3.1 修改密码
- 3.1.1 基本使用 alter
- 3.1.2 其他方式 mysqladmin
- 3.1.3 其他方式 set password
- 3.1.4 修改当前登录用户密码
- 3.2 密码过期设置
- 3.2.1 使密码立即过期 PASSWORD EXPIRE
- 3.2.2 使密码从不过期 EXPIRE NEVER
- 3.2.3 默认过期时间 PASSWORD EXPIRE DEFAULT
- 3.2.4 指定过期间隔 EXPIRE INTERVAL 90 DAY
- 3.3 set password
- 3.4 密码过期策略
- 3.4.1 全局参数
- 3.4.2 指定账户设置
一、访问控制
1.1 连接验证(阶段1)
当我们连接mysql的时候
- 通过提供的账号和密码来验证身份
- 验证账号是否锁定
服务首先检查凭据,然后检查账户的锁定状态。任一步骤失败都会拒绝访问,没有问题就接收连接。锁定状态记录在user表account_locked列中。
mysql> select user,account_locked from user;
+--------+----------------+
| user | account_locked |
+--------+----------------+
| root | N |
| multis | N |
| multis | N |
| root | N |
+--------+----------------+
4 rows in set (0.00 sec)
1.2 允许的连接
下表显示了如何将各种的组合User和Host值在 user表适用于传入的连接
User | Host | 允许的连接 |
---|---|---|
‘fred’ | h1.example.net | 来自h1.example.net的fred |
‘’ | ‘h1.example.net’ | 来自h1.example.net的任何用户 |
‘fred’ | ‘%’ | 任何主机的fred |
‘’ | ‘’ | 任何主机的任何用户 |
‘fred’ | ‘%.example.net’ | 从example.net的任何主机的fred |
‘fred’ | ‘x.example.net%’ | 从x.example.net,从x.example.com等的任何主机的fred |
‘fred’ | ‘198.51.100.177’ | 从ip198.51.100.177主机的fred |
‘fred’ | ‘198.51.100.%’ | 从ip198.51.100C类网中任何主机的fred |
‘fred’ | '198.51.100.0/255.255.255.0 | 与前面相同 |
1.3 连接的优先级
当有多个匹配项时,需要确认使用哪个匹配项,按照以下的方式解决问题
- 当服务器将user表读入内存,它会对user表进行排序
- 客户端尝试连接时,服务器将按排序顺序浏览各行
- 服务器使用与客户端主机名和用户名匹配的第一行
排序顺序
- 优先Host进行排序,其次User
- 有具体文字比%更具有高优先级(127.0.0.1比localhost高)
示例一
要查看其工作原理,假设user 表如下所示:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-
读入到内存时,自动排序后的结果如下所示:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-
挡localhost 上的root用户连接mysql时候,这个时候会匹配| localhost | root |这个条目对应的权限。 其他条目虽然也满足, 但不会匹配它们对应的权限。
示例二
创建如下两个用户,进行连接的优先级的测试
[root@mysql1 ~]# [root@mysql2 ~]# mysql -root-p123456
mysql> create user ''@'192.168.79.140' identified by '123456';
mysql> create user 'test'@'%' identified by '123456';
mysql> select host,user from user;
+----------------+------+
| host | user |
+----------------+------+
| % | test |
| 192.168.79.140 | |
| localhost | root |
+----------------+------+
3 rows in set (0.00 sec)
mysql> exit;
用刚才我们创建的用户登录mysql
[root@mysql2 ~]# mysql -utest -p123456 -h192.168.79.140
读入到内存时,自动排序后的结果如下所示:
+----------------+------+
| host | user |
+----------------+------+
| 192.168.79.140 | |
| localhost | root |
| % | test |
+----------------+------+
第一行匹配test的连接是| 192.168.79.140 | |
我们可以通过CURRENT_USER()函数查看,当前用户
mysql> select current_user();
+-----------------+
| current_user() |
+-----------------+
| @192.168.79.140 |
+-----------------+
1 row in set (0.00 sec)
建议生产不要有不带用户名只有主机的用户
1.4 请求验证(阶段二)
建立连接后,服务器进入访问控制的第二阶段。该连接发出的每个请求,会检查是否具有足够的权限。
这些权限对应着: user(用户),db(数据库),tables_priv(表),columns_priv(列),或procs_priv(存储过程),proxies_priv(代理用户权限) 这些表。
二、用户管理
我们需要知道的,mysql用户名和主机名在一起才是一个有效的用户。
2.1 新增用户
语法和Oracle是相似的,如下
create user 'user'@'localhost' identified by 'passwd' [ACCOUNT UNLOCK]
ACCOUNT UNLOCK 用户默认是没有锁定的,如果账户所有,我登录账号不会有第二阶段的请求验证。如下创建一个本地可以登陆的multis用户,默认账户为未锁定状态。
mysql> create user 'multis'@'localhost' identified by '123456' account unlock;
Query OK, 0 rows affected (0.00 sec)
2.2 用户修改
2.2.1 使用alter修改用户
查询用户状态
mysql> select user,host,account_locked from user;
+--------+-----------+----------------+
| user | host | account_locked |
+--------+-----------+----------------+
| root | localhost | N |
| multis | localhost | N |
+--------+-----------+----------------+
2 rows in set (0.00 sec)
1、使用alter修改用户状态
mysql> alter user 'multis'@'localhost' account lock;
Query OK, 0 rows affected (0.00 sec)mysql> select user,host,account_locked from user;
+--------+-----------+----------------+
| user | host | account_locked |
+--------+-----------+----------------+
| root | localhost | N |
| multis | localhost | Y |
+--------+-----------+----------------+
2 rows in set (0.00 sec)
重新打开一个窗口进行mysql登陆,登陆时候报错帐户被锁定
[root@mysql2 ~]# mysql -umultis -p
Enter password:
ERROR 3118 (HY000): Access denied for user 'multis'@'localhost'. Account is locked.
2、使用alter修改用户密码
mysql> alter user 'test'@'localhost' identified by '654321';
Query OK, 0 rows affected (0.01 sec)
2.2.2 DML语句管理mysql用户
直接更新mysql.user表的信息后,需要flush privileges,将内存和磁盘中的数据保持一致。
1、修改用户名
mysql> update mysql.user set user = 'test' where user = 'multis' and host='localhost';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
2、修改用户ip
mysql> update mysql.user set host = '127.0.0.1' where user = 'test' and host='localhost';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> select user,host,account_locked from user;
+------+-----------+----------------+
| user | host | account_locked |
+------+-----------+----------------+
| root | localhost | N |
| test | 127.0.0.1 | N |
+------+-----------+----------------+
2 rows in set (0.00 sec)
2.3 删除用户
方法一:
mysql> drop user 'test'@'localhost';
Query OK, 0 rows affected (0.00 sec
mysql> create user 'test'@'localhost' identified by '123456' account unlock;
Query OK, 0 rows affected (0.00 sec)
方案二:
mysql> create user 'test'@'localhost' identified by '123456' account unlock;
Query OK, 0 rows affected (0.00 sec)mysql> delete from mysql.user where user = 'test' and host='localhost';
Query OK, 1 row affected (0.00 sec)mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
2.4 查看用户
2.4.1 show create user 显示用户非权限属性
mysql> create user test@'localhost' identified by '123456';
Query OK, 0 rows affected (0.00 sec)mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
2.4.2 select from mysql.user 查看已经创建的用户
mysql> select * from mysql.user where user='test' and host='localhost' \G;
*************************** 1. row ***************************Host: localhostUser: testSelect_priv: NInsert_priv: NUpdate_priv: NDelete_priv: NCreate_priv: NDrop_priv: NReload_priv: NShutdown_priv: NProcess_priv: NFile_priv: NGrant_priv: NReferences_priv: NIndex_priv: NAlter_priv: NShow_db_priv: NSuper_priv: NCreate_tmp_table_priv: NLock_tables_priv: NExecute_priv: NRepl_slave_priv: NRepl_client_priv: NCreate_view_priv: NShow_view_priv: NCreate_routine_priv: NAlter_routine_priv: NCreate_user_priv: NEvent_priv: NTrigger_priv: N
Create_tablespace_priv: Nssl_type: ssl_cipher: x509_issuer: x509_subject: max_questions: 0max_updates: 0max_connections: 0max_user_connections: 0plugin: mysql_native_passwordauthentication_string: *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9password_expired: Npassword_last_changed: 2023-04-18 22:00:36password_lifetime: NULLaccount_locked: N
1 row in set (0.00 sec)ERROR:
No query specified
2.4.3 select current_user() 查看当前登录用户
mysql> select current_user;
+----------------+
| current_user |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
mysql> select user();
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
三、密码管理
3.1 修改密码
3.1.1 基本使用 alter
mysql> alter user 'test'@'localhost' identified by '654321';
Query OK, 0 rows affected (0.01 sec)
3.1.2 其他方式 mysqladmin
[root@mysql2 ~]# mysqladmin -utest -p654321 password
mysqladmin: [Warning] Using a password on the command line interface can be insecure.
New password:
Confirm new password:
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
3.1.3 其他方式 set password
1 、使用默认加密
mysql> set password for 'test'@'%' ='abcdefg';
Query OK, 0 rows affected (0.01 sec)
2、使用PASSWORD()函数加密(mysql使用该方式进行密码加密)
mysql> set password for 'test'@'%' =password('123456');
Query OK, 0 rows affected (0.01 sec)
3.1.4 修改当前登录用户密码
mysql> alter user current_user() identified by '123456';
Query OK, 0 rows affected (0.00 sec)mysql> alter user user() identified by '123456';
Query OK, 0 rows affected (0.00 sec)
3.2 密码过期设置
在设置密码过期时 identified by '123456'
可以忽略
3.2.1 使密码立即过期 PASSWORD EXPIRE
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
重置密码后才能正常登陆
1、修改用户密码过期
mysql> alter user 'test'@'localhost' identified by '123456' password expire;
Query OK, 0 rows affected (0.00 sec)mysql> show create user 'test'@localhost \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
2、我们可以发现密码策略从PASSWORD EXPIRE DEFAULT变为PASSWORD EXPIRE,登陆mysql,使用sql语句无法使用。
mysql> select current_user();
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
3、使用root用户修改密码
mysql> alter user 'test'@'localhost' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
4、密码修改完成,可以正常登陆mysql
[root@mysql2 ~]# mysql -utest -p123456
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)
3.2.2 使密码从不过期 EXPIRE NEVER
1、查询test用户非权限属性
mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
2、修改test用户密码永不过期
mysql> alter user 'test'@'localhost' identified by '123456' password expire;
Query OK, 0 rows affected (0.00 sec)
3、查询test用户非权限属性
mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE NEVER ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
3.2.3 默认过期时间 PASSWORD EXPIRE DEFAULT
1、查询test用户非权限属性
mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE NEVER ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
2、我们可以看出当前test密码是永不过期,我们修改为默认设置过期时间
mysql> alter user 'test'@'localhost' password expire default;
Query OK, 0 rows affected (0.01 sec)
3、查询test用户非权限属性
mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
3.2.4 指定过期间隔 EXPIRE INTERVAL 90 DAY
1、查询test用户非权限属性
mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
2、我们可以看出当前test密码是默认过期时间,我们修改为指定过期间隔
mysql> alter user 'test'@'localhost' password expire interval 90 day;
Query OK, 0 rows affected (0.00 sec)
3、查询test用户非权限属性
mysql> show create user 'test'@'localhost' \G;
*************************** 1. row ***************************
CREATE USER for test@localhost: CREATE USER 'test'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' REQUIRE NONE PASSWORD EXPIRE INTERVAL 90 DAY ACCOUNT UNLOCK
1 row in set (0.00 sec)ERROR:
No query specified
3.3 set password
使用Sset password修改密码有两种
1 、使用默认加密
mysql> set password for 'test'@'%' ='abcdefg';
Query OK, 0 rows affected (0.01 sec)
2、使用password()函数加密(mysql采用该方式进行密码的加密)
mysql> set password for 'test'@'%' =password('123456');
Query OK, 0 rows affected (0.01 sec)
3.4 密码过期策略
3.4.1 全局参数
我们可以使用select @@default_password_lifetime来查询密码过期的全局参数,默认值为0
mysql> select @@default_password_lifetime ;
+-----------------------------+
| @@default_password_lifetime |
+-----------------------------+
| 0 |
+-----------------------------+
1 row in set (0.00 sec)
如果需要修改全局参数,在服务器中my.cnf参数文件中修改或者添加default_password_lifetime参数,重启服务mysql服务生效
[mysqld]
default_password_lifetime=180
default_password_lifetime=180 密码有效期为6个月,最大值65535
default_password_lifetime=0 密码永不过期
1、停止mysql服务
mysql> shutdown;
Query OK, 0 rows affected (0.01 sec)mysql> exit
2、修改参数文件
[root@mysql2 ~]# vim /etc/my.cnf
[root@mysql2 ~]# cat /etc/my.cnf
3、启动mysql服务
[root@mysql2 ~]# nohup mysqld --defaults-file=/etc/my.cnf &
[root@mysql2 ~]# lsof -i:3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 1321 mysql 15u IPv6 24478 0t0 TCP *:mysql (LISTEN)
4、登陆msyql,查询全局参数
[root@mysql2 ~]# mysql -uroot -p123456
## 忽略mysql登陆部分 ##
mysql> select @@default_password_lifetime;
+-----------------------------+
| @@default_password_lifetime |
+-----------------------------+
| 180 |
+-----------------------------+
1 row in set (0.00 sec)
3.4.2 指定账户设置
现在要求每90天更改一次密码,我们可以创建用户的时候指定90天后密码过期
mysql> create user 'test1'@'localhost' identified by '123456' password expire interval 90 day;
Query OK, 0 rows affected (0.00 sec)
后续慢慢更新