MySQL 8.0 在用户管理方面增加了角色管理,默认的密码加密方式也做了调整,由之前的 SHA1 改为了 SHA2。同时加上 MySQL 5.7 的禁用用户和用户过期的功能,MySQL 在用户管理方面的功能和安全性都较之前版本大大的增强了。
在本教程中,我们将介绍 MySQL 下用户管理上的一些新特性和如何使用角色来简化权限管理。
注:本教程大部分特性要 MySQL 8.0 + 以上版本才支持。
MySQL 用户管理
验证插件和密码加密方式的变化
在 MySQL 8.0 中,caching_sha2_password 是默认的身份验证插件而不是之前版本的 mysql_native_password,默认的密码加密方式是 SHA2 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
mysql> show variables like 'default_authentication_plugin'; +-------------------------------+-----------------------+ | Variable_name | Value | +-------------------------------+-----------------------+ | default_authentication_plugin | caching_sha2_password | +-------------------------------+-----------------------+ 1 row in set (0.00 sec)
# 更新用户的密码加密方式为之前版本的方式 mysql> ALTER USER 'root'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY 'password'; # 刷新权限 mysql> FLUSH PRIVILEGES;
注:如果没有特殊的原因,建议使用更安全的新加密方式。
用户授权和修改密码
MySQL 8.0 的用户授权语句和之前版本有所区别,老版本的常用授权语句在 MySQL 8.0 版本中 已不能使用,如使用旧版本授权语句会报错。
在 MySQL 8.0 用之前版本授权语句创建用户。
1 2
mysql> GRANT ALL PRIVILEGES ON *.* TO `mike`@`%` IDENTIFIED BY '000000' WITH GRANT OPTION; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY '000000' WITH GRANT OPTION' at line 1
在 MySQL 8.0 版本中正确授权语句。
1 2
mysql> CREATE USER 'mike'@'%' IDENTIFIED BY '000000'; mysql> GRANT ALL ON *.* TO 'mike'@'%' WITH GRANT OPTION;
密码过期时间管理
MySQL 从 5.6.6 开始引入密码自动过期的新功能,并在 MySQL 5.7.4 版本中改进了用户密码过期时间这个特性。现在可以通过一个全局变量 default_password_lifetime 来设置一个全局的自动密码过期策略。
default_password_lifetime 其默认值为 0,表示禁用自动密码过期。default_password_lifetime 的值如是是正整数 N ,则表示允许的设置密码生存周期 为 N,单位为天 。
default_password_lifetime 全局密码到期策略默认为永久,不过期。
1 2 3 4 5 6 7
mysql> show variables like 'default_password_lifetime'; +---------------------------+-------+ | Variable_name | Value | +---------------------------+-------+ | default_password_lifetime | 0 | +---------------------------+-------+ 1 row in set (0.00 sec)
mysql> CREATE USER 'mike'@'%' IDENTIFIED BY '000000' PASSWORD EXPIRE INTERVAL 90 DAY; mysql> ALTER USER `mike`@`%` PASSWORD EXPIRE INTERVAL 90 DAY;
创建或修改一个用户的密码过期时间为永不过期。
1 2
mysql> CREATE USER 'mike'@'%' PASSWORD EXPIRE NEVER; mysql> ALTER USER 'mike'@'%' PASSWORD EXPIRE NEVER;
创建或修改一个遵循全局到期策略的用户。
1 2
mysql> CREATE USER 'mike'@'%' PASSWORD EXPIRE DEFAULT; mysql> ALTER USER 'mike'@'%' PASSWORD EXPIRE DEFAULT;
查看用户的密码过期时间。
1 2 3 4 5 6 7 8 9 10 11 12
mysql> select user,host,password_last_changed,password_lifetime,password_expired from mysql.user; +------------------+-----------+-----------------------+-------------------+------------------+ | user | host | password_last_changed | password_lifetime | password_expired | +------------------+-----------+-----------------------+-------------------+------------------+ | mike | % | 2018-05-07 11:13:39 | 90 | N | | root | % | 2018-05-04 16:46:05 | NULL | N | | mysql.infoschema | localhost | 2018-05-04 16:45:55 | NULL | N | | mysql.session | localhost | 2018-05-04 16:45:55 | NULL | N | | mysql.sys | localhost | 2018-05-04 16:45:55 | NULL | N | | root | localhost | 2018-05-04 16:46:05 | NULL | N | +------------------+-----------+-----------------------+-------------------+------------------+ 6 rows in set (0.00 sec)
锁定/解锁用户帐户
从 MySQL 5.7.8 开始,用户管理方面添加了锁定/解锁用户帐户的新特性。下面我们就来看下这个特性的一些具体示例。
创建一个带帐户锁的用户
1
mysql> CREATE USER 'mike-temp1'@'%' IDENTIFIED BY '000000' ACCOUNT LOCK;
接下来尝试用新创建的用户登陆,此时会得到一个 ERROR 3118 错误消息提示。
1 2 3
$ mysql -umike-temp1 -p000000 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 3118 (HY000): Access denied for user 'mike-temp1'@'172.22.0.1'. Account is locked.
如果你需要解锁此用户,此时就需要使用以下语句对其进行解锁了。
1 2
mysql> ALTER USER 'mike-temp1'@'%' ACCOUNT UNLOCK; Query OK, 0 rows affected (0.00 sec)
现在,这个用户就已经解锁,再次尝试登陆。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
$ mysql -umike-temp1 -p000000 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 10 Server version: 8.0.11 MySQL Community Server - GPL
Copyright (c) 2000, 2018, 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>
修改一个用户为锁定状态
如果用户已建立,你也可以这样锁定用户帐户。
1 2
mysql> ALTER USER 'mike'@'%' ACCOUNT LOCK; Query OK, 0 rows affected (0.00 sec)
设置 MySQL 用户密码重用策略
从 MySQL 8.0 开始允许限制重复使用以前的密码。可以根据密码更改次数、已用时间或两者来建立密码重用限制。帐户的密码历史由过去分配的密码组成,MySQL 可以限制从此历史记录中选择新密码。
mysql> SET PERSIST password_history = 6; mysql> SET PERSIST password_reuse_interval = 180;
MySQL 角色管理
MySQL 数据库中通常都会出现多个拥有相同权限集合的用户,在之前版本中只有分别向多个用户授予和撤销权限才能实现单独更改每个用户的权限。在用户数量比较多的时候,这样的操作是非常耗时的。
MySQL 8.0 为了用户权限管理更容易,提供了一个角色管理的新功能。角色是指定的权限集合,和用户帐户一样可以对角色进行权限的授予和撤消。如果用户被授予角色权限,则该用户拥有该角色的权限。
MySQL 8.0 提供的角色管理功能如下:
1 2 3 4 5 6 7 8
CREATE ROLE 角色创建 DROP ROLE 角色删除 GRANT 为用户和角色分配权限 REVOKE 为用户和角色撤销权限 SHOW GRANTS 显示用户和角色的权限 SET DEFAULT ROLE 指定哪些帐户角色默认处于活动状态 SET ROLE 更改当前会话中的活动角色 CURRENT_ROLE() 显示当前会话中的活动角色
创建角色并授予用户角色权限
这里我们以几种常见场景为例。
应用程序需要读/写权限。
运维人员需要完全访问数据库。
部分开发人员需要读取权限。
部分开发人员需要读写权限。
如果要向多个用户授予相同的权限集,则应按如下步骤来进行。
创建新的角色
授予角色权限
授予用户角色
首先,我们创建四个角色。为了清楚区分角色的权限,建议将角色名称命名得比较直观。
1
mysql> CREATE ROLE 'app', 'ops', 'dev_read', 'dev_write';
# 以下语句是向 app 角色授予 wordpress 数据库的读写权限 mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON wordpress.* TO 'app'; # 以下语句是向 ops 角色授予 wordpress 数据库的所有权限 mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'ops'; # 以下语句是向 dev_read 角色授予 wordpress 数据库的只读权限 mysql> GRANT SELECT ON wordpress.* TO 'dev_read'; # 以下语句是向 dev_write 角色授予 wordpress 数据库的写权限 mysql> GRANT INSERT, UPDATE, DELETE ON wordpress.* TO 'dev_write';
# 应用程序帐户 mysql> CREATE USER 'app01'@'%' IDENTIFIED BY '000000'; # 运维人员帐户 mysql> CREATE USER 'ops01'@'%' IDENTIFIED BY '000000'; # 开发人员只读帐户 mysql> CREATE USER 'dev01'@'%' IDENTIFIED BY '000000'; # 开发读写帐户 mysql> CREATE USER 'dev02'@'%' IDENTIFIED BY '000000'; mysql> CREATE USER 'dev03'@'%' IDENTIFIED BY '000000';
给用户分配角色
1 2 3
mysql> GRANT app TO 'app01'@'%'; mysql> GRANT ops TO 'ops01'@'%'; mysql> GRANT dev_read TO 'dev01'@'%';
如果要将多个用户同时加入多个角色,可以使用类似语句。
1
mysql> GRANT dev_read, dev_write TO 'dev02'@'%', 'dev03'@'%';
检查角色权限
要验证角色是否正确分配,可以使用 SHOW GRANTS 语句。
1 2 3 4 5 6 7 8
mysql> SHOW GRANTS FOR 'dev01'@'%'; +-------------------------------------+ | Grants for dev01@% | +-------------------------------------+ | GRANT USAGE ON *.* TO `dev01`@`%` | | GRANT `dev_read`@`%` TO `dev01`@`%` | +-------------------------------------+ 2 rows in set (0.00 sec)
正如你所看到的,和之前版本不同的是 SHOW GRANTS 只返回授予角色。如果要显示角色所代表的权限,需要加上 USING 子句和授权角色的名称。
1 2 3 4 5 6 7 8 9
mysql> SHOW GRANTS FOR 'dev01'@'%' USING dev_read; +----------------------------------------------+ | Grants for dev01@% | +----------------------------------------------+ | GRANT USAGE ON *.* TO `dev01`@`%` | | GRANT SELECT ON `wordpress`.* TO `dev01`@`%` | | GRANT `dev_read`@`%` TO `dev01`@`%` | +----------------------------------------------+ 3 rows in set (0.00 sec)
$ mysql -u dev01 -p000000 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 11 Server version: 8.0.11 MySQL Community Server - GPL
Copyright (c) 2000, 2018, 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> use wordpress; ERROR 1044 (42000): Access denied for user 'dev01'@'%' to database 'wordpress'
$ mysql -u dev01 -p000000 Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 11 Server version: 8.0.11 MySQL Community Server - GPL
Copyright (c) 2000, 2018, 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> SHOW GRANTS FOR 'dev02'@'%' USING 'dev_read', 'dev_write'; +----------------------------------------------------------------------+ | Grants for dev02@% | +----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO `dev02`@`%` | | GRANT SELECT, INSERT, UPDATE, DELETE ON `wordpress`.* TO `dev02`@`%` | | GRANT `dev_read`@`%`,`dev_write`@`%` TO `dev02`@`%` | +----------------------------------------------------------------------+ 3 rows in set (0.00 sec)
接下来从 dev_write 角色中撤消掉修改权限。
1 2
mysql> REVOKE INSERT, UPDATE, DELETE ON wordpress.* FROM 'dev_write'; Query OK, 0 rows affected (0.03 sec)
最后我们在来看看 dev02 用户帐户当前权限。
1 2 3 4 5 6 7 8 9
mysql> SHOW GRANTS FOR 'dev02'@'%' USING 'dev_read', 'dev_write'; +-----------------------------------------------------+ | Grants for dev02@% | +-----------------------------------------------------+ | GRANT USAGE ON *.* TO `dev02`@`%` | | GRANT SELECT ON `wordpress`.* TO `dev02`@`%` | | GRANT `dev_read`@`%`,`dev_write`@`%` TO `dev02`@`%` | +-----------------------------------------------------+ 3 rows in set (0.00 sec)
# 授予 dev_write 角色修改权限。 mysql> GRANT INSERT, UPDATE, DELETE ON wordpress.* TO 'dev_write';
# 再次查看 dev02 用户权限,修改权限已经恢复。 mysql> SHOW GRANTS FOR 'dev02'@'%' USING 'dev_read', 'dev_write'; +----------------------------------------------------------------------+ | Grants for dev02@% | +----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO `dev02`@`%` | | GRANT SELECT, INSERT, UPDATE, DELETE ON `wordpress`.* TO `dev02`@`%` | | GRANT `dev_read`@`%`,`dev_write`@`%` TO `dev02`@`%` | +----------------------------------------------------------------------+ 3 rows in set (0.00 sec)
MySQL 8.0 将每一个用户帐户视为角色,因此可以将用户帐户授予另一个用户帐户。例如:将一开发人员帐号权限复制到另一开发人员帐号。
创建一个新的开发用户帐户
1 2
mysql> CREATE USER 'dev04'@'%' IDENTIFIED BY '000000'; Query OK, 0 rows affected (0.04 sec)
将 dev02 用户帐户的权限复制到 dev04 用户帐户
1 2
mysql> GRANT 'dev02'@'%' TO 'dev04'@'%'; Query OK, 0 rows affected (0.09 sec)
查看 dev04 用户帐户的权限
1 2 3 4 5 6 7 8 9
mysql> SHOW GRANTS FOR 'dev04'@'%' USING 'dev02'; +----------------------------------------------------------------------+ | Grants for dev04@% | +----------------------------------------------------------------------+ | GRANT USAGE ON *.* TO `dev04`@`%` | | GRANT SELECT, INSERT, UPDATE, DELETE ON `wordpress`.* TO `dev04`@`%` | | GRANT `dev02`@`%` TO `dev04`@`%` | +----------------------------------------------------------------------+ 3 rows in set (0.00 sec)