0
点赞
收藏
分享

微信扫一扫

如何添加一个 mysql 用户并给予权限?

Greatiga 2024-02-01 阅读 12

添加用户并赋予权限是一个很简单的操作,在不同版本略有区别。但下一步就会涉及到如何设计用户安全加固的部分。

基于安全的背景下,客户对 MySQL 的用户安全上提出了一系列需求,希望能对 MySQL 进行安全加固,具体的需求如下:

用户密码类

  • 密码需要至少 25 个字符
  • 密码必须包含至少 2 个大写字母
  • 密码必须包含至少 2 个小写字母
  • 密码必须包含至少 2 个数字
  • 密码必须包含至少 2 个特殊字符
  • 密码中不能包含用户名
  • 密码不能是简单的重复字符(例如:AAA,wuwuwu, dsadsadsa, 111)


  • 密码需要有过期时间,需要 365 天修改一次,否则过期并锁定用户
  • 密码不得使用历史 5 次内曾用过的老密码
  • 密码在 24 小时内最多只能修改一次
  • 密码不能包含指定的字符,如公司名称、业务名称等用户连接类
  • 登录时如果连续 10 次失败,需要等待 10 分钟且每次失败持续增加等待时间

需求分析

基于背景描述我们可以把需求分为三大块:

  • 密码复杂度策略
  • 连接控制的策略
  • 密码变更的策略

MySQL 有以下功能插件/组件、配置可实现以上需求:

  • 密码校验插件/组件
  • 插件
  • 用户密码属性配置MySQL 版本:8.0.33、5.7.41

安装配置

1. 密码校验组件配置

MySQL 5.7 版本为密码校验插件,虽然安装方式和变量有语法有些许差异,但功能基本相同。以下操作仅以 MySQL 8.0 版本操作为例.

## 8.0 版本安装密码校验组件
INSTALL COMPONENT 'file://component_validate_password';

## 查看插件默认配置
show variables like 'validate_password%';
+--------------------------------------+--------+
| Variable_name                        | Value  |
+--------------------------------------+--------+
| validate_password.check_user_name    | ON     |    ## 密码不能包含用户名
| validate_password.dictionary_file    |        |    ## 指定密码匹配字典文件,在文件中的字符串不能包含在设置的密码中,在 policy 为 STRONG 时有效
| validate_password.length             | 8      |    ## 密码最小长度,默认至少 8 位长
| validate_password.mixed_case_count   | 1      |    ## 密码至少包含 1 个大小写字母
| validate_password.number_count       | 1      |    ## 密码至少包含一个数字
| validate_password.policy             | MEDIUM |    ## 密码默认复杂度策略
| validate_password.special_char_count | 1      |    ## 密码至少包含一个特殊字符
+--------------------------------------+--------+
7 rows in set (0.0042 sec)

## 修改配置以便符合背景需求
set global validate_password.length=25;
set global validate_password.mixed_case_count=2;
set global validate_password.number_count=2;
set global validate_password.special_char_count=2;

## 查看调整后的配置(动态生效)
show variables like 'validate_password%';
+--------------------------------------+--------+
| Variable_name                        | Value  |
+--------------------------------------+--------+
| validate_password.check_user_name    | ON     |
| validate_password.dictionary_file    |        |
| validate_password.length             | 25     |
| validate_password.mixed_case_count   | 2      |
| validate_password.number_count       | 2      |
| validate_password.policy             | MEDIUM |
| validate_password.special_char_count | 2      |
+--------------------------------------+--------+
7 rows in set (0.0056 sec)

## 持久化配置到 my.cnf 配置文件(永久生效)
## 在 [mysqld] 标签下增加配置
vim /data/mysql/3306/my.cnf.3306 
[mysqld]
## 密码校验组件参数配置
validate_password.check_user_name     = ON
validate_password.policy              = MEDIUM
validate_password.length              = 25
validate_password.mixed_case_count    = 2
validate_password.number_count        = 2
validate_password.special_char_count  = 2

2. 连接控制插件配置

在 MySQL 5.7 和 MySQL 8.0 基本无变化,均以插件形式提供。以下操作仅以 MySQL 8.0 版本操作为例.

## 连接控制插件安装
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';

## 查看插件默认配置
show variables like 'connection_control%';
+-------------------------------------------------+------------+
| Variable_name                                   | Value      |
+-------------------------------------------------+------------+
| connection_control_failed_connections_threshold | 3          | ## 运行登录失败尝试的次数,默认为 3,表示当连接失败 3 次后启用连接控制,0 表示不开启
| connection_control_max_connection_delay         | 2147483647 | ## 响应延迟的最大时间,默认约25天
| connection_control_min_connection_delay         | 1000       | ## 登录失败后响应延迟的最小时间,默认 1000 毫秒,1 秒,每失败一次逐步累加,直到最大值
+-------------------------------------------------+------------+

## 修改配置以便符合背景需求,响应延迟的最大时间设置为 1 天
set global connection_control_max_connection_delay=24*60*60*1000;

## 查看调整后的配置(动态生效)
show variables like 'connection_control%';
+-------------------------------------------------+-------+
| Variable_name                                   | Value |
+-------------------------------------------------+-------+
| connection_control_failed_connections_threshold | 3     |
| connection_control_max_connection_delay         | 86400000 | ## 调整为最大一天
| connection_control_min_connection_delay         | 1000  |
+-------------------------------------------------+-------+

## 持久化配置到 my.cnf 配置文件(永久生效)
## 在 [mysqld] 标签下增加配置
vim /data/mysql/3306/my.cnf.3306 
[mysqld]
## 连接控制插件配置
connection-control                                     = FORCE
connection-control-failed-login-attempts               = FORCE
connection_control_min_connection_delay                = 1000
connection_control_max_connection_delay                = 86400000
connection_control_failed_connections_threshold        = 3

3. 密码变更策略配置

MySQL 密码变更策略配置记录在 mysql.user 表中,5.7 和 8.0 版本支持的配置略有差异,具体细节可参考官方文档中 CREATE USERALTER USER 语法中 password_option 部分属性说明。

相关配置参数含义说明

MySQL 5.7 版本下仅支持:

default_password_lifetime

注意:线上环境配置密码过期策略虽然可提升安全性,但如果没及时更新密码会导致业务中断问题,需要综合评估后配置!

MySQL 8.0 版本支持:

default_password_lifetime:密码有效期(默认为 0 或 NULL),表示密码永久有效。

注意:线上环境配置密码过期策略虽然可提升安全性,但如果没及时更新密码会导致业务中断问题,需要综合评估后配置!

password_history:历史密码可重用的循环,表示记录历史上前多少次密码不允许被重复使用,历史密码信息记录在 mysql.password_history 表中。

password_reuse_interval:指定历史密码要经过多长时间才能被重用,单位为天。

关于 default_password_lifetime、password_history 以及 password_reuse_interval 在 my.cnf 配置后,创建用户默认属性不生效的问题,提了 MySQL Bug,待官方反馈是否符合预期。
结论:不是 Bug,对参数的理解有误。
以密码过期配置为示例说明,password_reuse_intervalpassword_history 均为相同逻辑。

  • ALTER USER eee PASSWORD EXPIRE;
  • eee 用户密码立即过期,mysql.user 表中 password_expired 字段标记为 Y


  • ALTER USER eee PASSWORD EXPIRE DEFAULT;
  • eee 用户密码过期策略采用全局参数 default_password_lifetime 指定的值作为过期策略,mysql.user 表中的 password_lifetime


  • ALTER USER eee PASSWORD EXPIRE NEVER;
  • eee 用户密码过期策略设置为永不过期,mysql.user 表中的 password_lifetime 字段值为 0


  • ALTER USER eee
  • eee 用户密码过期策略设置为指定 3 天后过期,mysql.user 表中的 password_lifetime 字段值为 3




<img src="https://picx.zhimg.com/50/v2-c434ea2c9314e98be1269d17e54767ed_720w.jpg?source=1def8aca" data-captinotallow="" data-size="normal" data-rawwidth="1563" data-rawheight="643" data-original-token="v2-c434ea2c9314e98be1269d17e54767ed" class="origin_image zh-lightbox-thumb" width="1563" data-original="https://picx.zhimg.com/v2-c434ea2c9314e98be1269d17e54767ed_r.jpg?source=1def8aca">

如何添加一个 mysql 用户并给予权限?_MySQL


关于 password_historypassword_reuse_interval 参数同时使用时,实际只有 password_reuse_interval 参数有效的问题,提了 MySQL Bug,待官方反馈是否符合预期。

################## 以5.7版本为例 ##################
## 1. 修改当前默认密码策略为需求所需配置(动态生效)
set global default_password_lifetime=365;

## 2. 查看当前密码有效期配置。这里一定注意,表中的password_lifetime为NULL不是表示无策略,而是表示使用default_password_lifetime参数指定的全局策略
select user,host,password_lifetime from mysql.user where user not in  ('mysql.session','mysql.sys');
+----------+-----------+-------------------+
| user     | host      | password_lifetime |
+----------+-----------+-------------------+
| root     | localhost |              NULL |
| zhenxing | %         |              NULL |
| sysbench | %         |              NULL |
| aaa      | %         |              NULL |
| bbb      | %         |              NULL |
+----------+-----------+-------------------+

## 3. 持久化当前默认密码策略为需求所需配置(永久生效)
## 在[mysqld]标签下增加配置
vim /data/mysql/3306/my.cnf.3306 
[mysqld]
## 密码策略配置
default_password_lifetime = 365

################## 以8.0版本为例 ##################
## 1. 修改当前默认密码策略为需求所需配置(动态生效)
set global default_password_lifetime=365;
set global password_history=5;
set global password_reuse_interval=1;

## 2. 查看当前已存在用户的密码策略配置(默认均为NULL,表示使用default_password_lifetime、password_history、password_reuse_interval参数指定的全局策略)
select user,host,password_lifetime,Password_reuse_history,Password_reuse_time from mysql.user where user not in ('mysql.infoschema','mysql.session','mysql.sys');
+----------+-----------+-------------------+------------------------+---------------------+
| user     | host      | password_lifetime | Password_reuse_history | Password_reuse_time |
+----------+-----------+-------------------+------------------------+---------------------+
| aaa      | %         |              NULL |                   NULL |                NULL |
| sysbench | %         |              NULL |                   NULL |                NULL |
| zhenxing | %         |              NULL |                   NULL |                NULL |
| backup   | 127.0.0.1 |              NULL |                   NULL |                NULL |
| backup   | localhost |              NULL |                   NULL |                NULL |
| root     | localhost |              NULL |                   NULL |                NULL |
+----------+-----------+-------------------+------------------------+---------------------

## 3. 持久化当前默认密码策略为需求所需配置(永久生效)
## 在[mysqld]标签下增加配置
vim /data/mysql/3306/my.cnf.3306 
[mysqld]
## 密码策略配置
default_password_lifetime = 365
password_history          = 5
password_reuse_interval   = 1

举报

相关推荐

0 条评论