MySQL 8.0用户和角色管理

MySQL 8.0 正式版目前已发布,MySQL 8.0 增长了不少新的功能,具体可参考「MySQL 8.0 正式版 8.0.11 发布!」一文。mysql

MySQL 8.0 在用户管理方面增长了角色管理,默认的密码加密方式也作了调整,由以前的 SHA1 改成了 SHA2。同时加上 MySQL 5.7 的禁用用户和用户过时的功能,MySQL 在用户管理方面的功能和安全性都较以前版本大大的加强了。sql

在本教程中,咱们将介绍 MySQL 下用户管理上的一些新特性和如何使用角色来简化权限管理。数据库

注:本教程大部分特性要 MySQL 8.0 + 以上版本才支持。安全

MySQL 用户管理

验证插件和密码加密方式的变化

在 MySQL 8.0 中,caching_sha2_password 是默认的身份验证插件而不是以前版本的 mysql_native_password,默认的密码加密方式是 SHA2bash

mysql> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name                 | Value                 |
+-------------------------------+-----------------------+
| default_authentication_plugin | caching_sha2_password |
+-------------------------------+-----------------------+
1 row in set (0.00 sec)

mysql> select user,host,plugin from mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | mysql_native_password |
| mysql.session    | localhost | mysql_native_password |
| mysql.sys        | localhost | mysql_native_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)复制代码

若是须要保持以前的验证方式并保持以前版本的密码加密方式须要在配置文件 my.cnf 中修改如下配置项并重启服务后生效。服务器

[mysqld]
default_authentication_plugin = mysql_native_password复制代码

注:此选项暂不支持 MySQL 8.0 动态修改特性。session

将 MySQL 8.0 中已有的 SHA2 密码修改成 SHA1 的模式。app

# 更新用户的密码加密方式为以前版本的方式
mysql> ALTER USER 'root'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY 'password';
# 刷新权限
mysql> FLUSH PRIVILEGES;复制代码

注:若是没有特殊的缘由,建议使用更安全的新加密方式。运维

用户受权和修改密码

MySQL 8.0 的用户受权语句和以前版本有所区别,老版本的经常使用受权语句在 MySQL 8.0 版本中 已不能使用,如使用旧版本受权语句会报错。wordpress

  • 在 MySQL 8.0 用以前版本受权语句建立用户。

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 版本中正确受权语句。

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 全局密码到期策略默认为永久,不过时。

mysql> show variables like 'default_password_lifetime';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| default_password_lifetime | 0     |
+---------------------------+-------+
1 row in set (0.00 sec)复制代码
  • 若是你要创建一个全局策略,让全部用户的密码的使用期限为六个月,可在服务端配置文件 my.cnf 中修改 default_password_lifetime 配置项的值为 180。

[mysqld]
default_password_lifetime=180复制代码
  • 若是你要恢复全局策略,让全部用户的密码永不过时,可在服务端配置文件 my.cnf 中修改 default_password_lifetime 配置项的值为 0。

[mysqld]
default_password_lifetime=0复制代码
  • default_password_lifetime 参数是支持永久动态设置的,你也能够用如下命令在 MySQL 命令行下直接设置生效。

# 设置默认密码过时策略为 180 天后过时
mysql> SET PERSIST default_password_lifetime = 180;

# 设置默认密码过时策略为永不过时
mysql> SET PERSIST default_password_lifetime = 0;

# MySQL 8.0 永久动态修改参数会保存在配置文件 mysqld-auto.cnf 中,保存的格式为JSON串。
$ cat  /var/lib/mysql/mysqld-auto.cnf
{ "Version" : 1 , "mysql_server" : { "default_password_lifetime" : { "Value" : "180" , "Metadata" : { "Timestamp" : 1525663928688419 , "User" : "root" , "Host" : "" } } } }复制代码
  • 建立和修改带有密码过时时间的用户示例

建立或修改一个用户的密码过时时间为 90 天。

mysql> CREATE USER 'mike'@'%' IDENTIFIED BY '000000' PASSWORD EXPIRE INTERVAL 90 DAY;
mysql> ALTER USER `mike`@`%` PASSWORD EXPIRE INTERVAL 90 DAY;复制代码

建立或修改一个用户的密码过时时间为永不过时。

mysql> CREATE USER 'mike'@'%' PASSWORD EXPIRE NEVER;
mysql> ALTER USER 'mike'@'%' PASSWORD EXPIRE NEVER;复制代码

建立或修改一个遵循全局到期策略的用户。

mysql> CREATE USER 'mike'@'%' PASSWORD EXPIRE DEFAULT;
mysql> ALTER USER 'mike'@'%' PASSWORD EXPIRE DEFAULT;复制代码

查看用户的密码过时时间。

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 开始,用户管理方面添加了锁定/解锁用户账户的新特性。下面咱们就来看下这个特性的一些具体示例。

  • 建立一个带账户锁的用户

mysql> CREATE USER 'mike-temp1'@'%' IDENTIFIED BY '000000' ACCOUNT LOCK;复制代码

接下来尝试用新建立的用户登录,此时会获得一个 ERROR 3118 错误消息提示。

$ 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.复制代码

若是你须要解锁此用户,此时就须要使用如下语句对其进行解锁了。

mysql> ALTER USER 'mike-temp1'@'%' ACCOUNT UNLOCK;
Query OK, 0 rows affected (0.00 sec)复制代码

如今,这个用户就已经解锁,再次尝试登录。

$ 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>复制代码
  • 修改一个用户为锁定状态

若是用户已创建,你也能够这样锁定用户账户。

mysql> ALTER USER 'mike'@'%' ACCOUNT LOCK;
Query OK, 0 rows affected (0.00 sec)复制代码

设置 MySQL 用户密码重用策略

从 MySQL 8.0 开始容许限制重复使用之前的密码。能够根据密码更改次数、已用时间或二者来创建密码重用限制。账户的密码历史由过去分配的密码组成,MySQL 能够限制今后历史记录中选择新密码。

  • 若是根据密码更改次数限制账户,则没法从指定数量的最新密码中选择新密码。例如:若是密码更改的最小数量设置为 3,则新密码不能与任何最近的3个密码相同。

  • 若是根据密码修改时间来限制账户,则没法将指定时间历史记录中的密码中选择为新密码。例如:若是密码重用间隔设置为 60,则新密码不得在最近 60 天内选择的密码相同。

注:空密码不记录在密码历史记录中,并随时能够重复使用。

要创建全局密码重用策略,可修改 password_historypassword_reuse_interval 系统变量。该变量可在服务配置文件 my.cnf 中配置,以禁止重复使用最近 6 个密码或最近 180 天内使用过的任何密码为例。

[mysqld]
password_history=6
password_reuse_interval=180复制代码

该参数是支持永久动态设置,也能够直接用下面语句进行设置。

mysql> SET PERSIST password_history = 6;
mysql> SET PERSIST password_reuse_interval = 180;复制代码

MySQL 角色管理

MySQL 数据库中一般都会出现多个拥有相同权限集合的用户,在以前版本中只有分别向多个用户授予和撤销权限才能实现单独更改每一个用户的权限。在用户数量比较多的时候,这样的操做是很是耗时的。

MySQL 8.0 为了用户权限管理更容易,提供了一个角色管理的新功能。角色是指定的权限集合,和用户账户同样能够对角色进行权限的授予和撤消。若是用户被授予角色权限,则该用户拥有该角色的权限。

MySQL 8.0 提供的角色管理功能以下:

CREATE ROLE 角色建立
DROP ROLE 角色删除
GRANT 为用户和角色分配权限
REVOKE 为用户和角色撤销权限
SHOW GRANTS 显示用户和角色的权限
SET DEFAULT ROLE 指定哪些账户角色默认处于活动状态
SET ROLE 更改当前会话中的活动角色
CURRENT_ROLE() 显示当前会话中的活动角色复制代码

建立角色并授予用户角色权限

这里咱们以几种常见场景为例。

  • 应用程序须要读/写权限。

  • 运维人员须要彻底访问数据库。

  • 部分开发人员须要读取权限。

  • 部分开发人员须要读写权限。

若是要向多个用户授予相同的权限集,则应按以下步骤来进行。

  • 建立新的角色

  • 授予角色权限

  • 授予用户角色

首先,咱们建立四个角色。为了清楚区分角色的权限,建议将角色名称命名得比较直观。

mysql> CREATE ROLE 'app', 'ops', 'dev_read', 'dev_write';复制代码

注:角色名称格式相似于由用户和主机部分组成的用户账户,如:role_name@host_name。若是省略主机部分,则默认为 “%”,表示任何主机。

建立好角色后,咱们就给角色授予对应的权限。要授予角色权限,您可使用 GRANT语句。

# 如下语句是向 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';复制代码

注:这里假定需受权的数据库名称为 wordpress。

最后根据实际状况,咱们将指定用户加入到对应的角色。假设须要一个应用程序使用的账户、一个运维人员账户、一个是开发人员只读账户和两个开发人员读写账户。

  • 建立新用户

# 应用程序账户
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';复制代码
  • 给用户分配角色

mysql> GRANT app TO 'app01'@'%';
mysql> GRANT ops TO 'ops01'@'%';
mysql> GRANT dev_read TO 'dev01'@'%';复制代码

若是要将多个用户同时加入多个角色,可使用相似语句。

mysql> GRANT dev_read, dev_write TO 'dev02'@'%', 'dev03'@'%';复制代码

检查角色权限

要验证角色是否正确分配,可使用 SHOW GRANTS 语句。

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 子句和受权角色的名称。

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)复制代码

设置默认角色

如今,若是您使用 dev01 用户账户链接到 MySQL,并尝试访问 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> use wordpress;
ERROR 1044 (42000): Access denied for user 'dev01'@'%' to database 'wordpress'复制代码

这是由于在向用户账户授予角色后,当用户账户链接到数据库服务器时,它并不会自动使角色变为活动状态。

# 调用 CURRENT_ROLE() 函数查看当前角色。
mysql> SELECT current_role();
+----------------+
| current_role() |
+----------------+
| NONE           |
+----------------+
1 row in set (0.00 sec)复制代码

这里返回 NONE,就意味着当前没有启用任何角色。要在每次用户账户链接到数据库服务器时指定哪些角色应该处于活动状态,需用使用 SET DEFAULT ROLE 语句来指定。

# 如下语句将把 dev01 账户分配的全部角色都设置为默认值。
mysql> SET DEFAULT ROLE ALL TO 'dev01'@'%';复制代码

再次使用 dev01 用户账户链接到 MySQL 数据库服务器并调用 CURRENT_ROLE() 函数,您将看到 dev01 用户账户的默认角色。

$ 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>

# 查看 dev01 用户账户的默认角色。
mysql> SELECT current_role();
+----------------+
| current_role() |
+----------------+
| `dev_read`@`%` |
+----------------+
1 row in set (0.00 sec)复制代码

最后经过将当前数据库切换到 wordpress 数据库,并执行 SELECT 语句和 DELETE 语句来测试 dev01 账户的权限。

mysql> use wordpress;
Database changed

mysql> select  count(*) from wp_terms;
+----------+
| count(*) |
+----------+
|      357 |
+----------+
1 row in set (0.00 sec)

mysql> DELETE from wp_terms;
ERROR 1142 (42000): DELETE command denied to user 'dev01'@'172.22.0.1' for table 'wp_terms'复制代码

如上面结果所示,当咱们发出 DELETE 语句时,就收到一个错误。由于 dev01 用户账户只有读取访问权限。

设置活动角色

用户账户能够经过指定哪一个受权角色处于活动状态来修改当前用户在当前会话中的有效权限。

  • 将活动角色设置为 NONE,表示没有活动角色。

mysql> SET ROLE NONE;复制代码
  • 将活动角色设置为全部授予的角色。

mysql> SET ROLE ALL;复制代码
  • 将活动角色设置为由 SET DEFAULT ROLE 语句设置的默认角色。

mysql> SET ROLE DEFAULT;复制代码
  • 同时设置多个活动的角色。

mysql> SET ROLE granted_role_1, granted_role_2, ...复制代码

撤消角色或角色权限

正如能够受权某个用户的角色同样,也能够从用户账户中撤销这些角色。要从用户账户中撤销角色须要使用 REVOKE 语句。

mysql> REVOKE role FROM user;复制代码

REVOKE 也能够用于修改角色权限。这不只影响角色自己权限,还影响任何授予该角色的用户权限。假设想临时让全部开发用户只读,可使用 REVOKE 从 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)复制代码

接下来从 dev_write 角色中撤消掉修改权限。

mysql> REVOKE INSERT, UPDATE, DELETE ON wordpress.* FROM 'dev_write';
Query OK, 0 rows affected (0.03 sec)复制代码

最后咱们在来看看 dev02 用户账户当前权限。

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)复制代码

从上面的结果能够看出,角色中撤销权限会影响到该角色中任何用户的权限。所以 dev02 如今已经没有表修改权限(INSERT,UPDATE,和 DELETE 权限已经去掉)。若是要恢复角色的修改权限,只需从新授予它们便可。

# 授予 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)复制代码

删除角色

要删除一个或多个角色,可使用 DROP ROLE 语句。

mysql> DROP ROLE 'role_name', 'role_name', ...;复制代码

如同 REVOKE 语句同样,删除角色会从受权它的每一个账户中撤消该角色。例如,要删除 dev_read,dev_write角色,可以使用如下语句。

mysql> DROP ROLE 'dev_read', 'dev_write';复制代码

复制用户账户权限到另外一个用户

MySQL 8.0 将每个用户账户视为角色,所以能够将用户账户授予另外一个用户账户。例如:将一开发人员账号权限复制到另外一开发人员账号。

  • 建立一个新的开发用户账户

mysql> CREATE USER 'dev04'@'%' IDENTIFIED BY '000000';
Query OK, 0 rows affected (0.04 sec)复制代码
  • 将 dev02 用户账户的权限复制到 dev04 用户账户

mysql> GRANT 'dev02'@'%' TO 'dev04'@'%';
Query OK, 0 rows affected (0.09 sec)复制代码
  • 查看 dev04 用户账户的权限

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)复制代码

参考文档

http://www.google.com
http://t.cn/RuTna0t
http://t.cn/RuTnEPH
http://t.cn/RuTnFGz
http://t.cn/RuTnFGz


若是你以为内容很赞,还等什么?快快长按打赏吧,iOS的土豪们也是能够的哟!




相关文章
相关标签/搜索