MySQL 密码管理

一、支持的功能

MySQL 通过 validate_password 组件实现以下功能:

  • 密码到期更改密码
  • 密码重用限制(阻止重用旧密码)
  • 密码验证(更改密码时需提供当前密码)
  • 双密码(主密码 + 第二密码)
  • 密码强度评估(要求使用强密码)
  • 生成随机密码
  • 密码错误跟踪(多次登录失败临时锁定)

二、内部与外部凭证存储

1. 帐户凭证存储

帐户凭证保存在系统表 mysql.user 中。

2. 内部身份验证插件

  • mysql_native_password:已弃用
  • caching_sha2_password:默认插件
  • sha256_password

三、密码过期策略

1. 自动过期策略

(1)系统变量

  • default_password_lifetime=N:设置密码过期时间(单位:天),全局策略。默认值为 0,表示密码永不过期。

(2)配置方式

  • 修改配置文件 /etc/my.cnf

    [mysqld]
    default_password_lifetime=180  # 180 天后过期
    # default_password_lifetime=0  # 密码永不过期
    
  • 动态持久化设置

    SET PERSIST default_password_lifetime = 180;  # 设置 180 天过期
    SET PERSIST default_password_lifetime = 0;    # 设置永不过期
    

2. 手动使密码过期

(1)语法

手动设置会覆盖全局策略,语法如下:

ALTER|CREATE USER ... PASSWORD EXPIRE {INTERVAL N DAY|NEVER|DEFAULT}

(2)示例

  • 设置密码过期时间(90 天)

    CREATE USER zabbix@localhost PASSWORD EXPIRE INTERVAL 90 DAY;
    ALTER USER zabbix@localhost PASSWORD EXPIRE INTERVAL 90 DAY;
    
  • 设置密码永不过期

    CREATE USER zabbix@localhost PASSWORD EXPIRE NEVER;
    ALTER USER zabbix@localhost PASSWORD EXPIRE NEVER;
    
  • 遵循全局密码过期策略

    CREATE USER zabbix@localhost PASSWORD EXPIRE DEFAULT;
    ALTER USER zabbix@localhost PASSWORD EXPIRE DEFAULT;
    

四、密码重用策略

1. 密码历史特点

  • 限制从密码历史记录中选择新密码
  • 空密码不记录在密码历史中,且始终拒绝重用

2. 限制方式

  • 基于密码更改次数:新密码不能与最近 N 个密码相同
  • 基于过去时间:新密码不能与最近 N 天使用过的密码相同

3. 全局密码重用策略

(1)系统变量

  • password_history=N:新密码不能与最近 N 个密码相同
  • password_reuse_interval=N:新密码不能与最近 N 天使用过的密码相同

(2)配置方式

  • 修改配置文件 /etc/my.cnf

    [mysqld]
    password_history=6        # 不允许重用最近 6 个密码
    password_reuse_interval=365  # 不允许重用最近 365 天的密码
    
  • 动态持久化设置

    SET PERSIST password_history = 6;
    SET PERSIST password_reuse_interval = 365;
    

4. 单个账户密码重用策略

(1)语法

单个账户策略会覆盖全局策略,语法如下:

CREATE | ALTER USER ... {PASSWORD HISTORY N | PASSWORD REUSE INTERVAL N DAY}

(2)示例

  • 新密码不能与最近 5 个密码相同

    CREATE USER zabbix@localhost PASSWORD HISTORY 5;
    ALTER USER zabbix@localhost PASSWORD HISTORY 5;
    
  • 新密码不能与最近 365 天使用过的密码相同

    CREATE USER zabbix@localhost PASSWORD REUSE INTERVAL 365 DAY;
    ALTER USER zabbix@localhost PASSWORD REUSE INTERVAL 365 DAY;
    
  • 合并设置(同时限制次数和时间)

    CREATE USER zabbix@localhost PASSWORD HISTORY 5 PASSWORD REUSE INTERVAL 365 DAY;
    ALTER USER zabbix@localhost PASSWORD HISTORY 5 PASSWORD REUSE INTERVAL 365 DAY;
    
  • 恢复全局默认设置

    CREATE USER zabbix@localhost PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT;
    ALTER USER zabbix@localhost PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT;
    

五、密码验证策略

1. 概述

密码验证指更改账户密码时需提供当前密码,相关数据保存在 mysql.user 系统表中。

2. 全局密码验证策略

(1)系统变量

  • default_authentication_plugin:默认身份验证插件
  • password_require_current:是否需要指定当前密码(默认禁用)。拥有 CREATE USER 全局权限或对 mysql 库有 UPDATE 权限的账户可无视此策略。

(2)配置方式

  • 修改配置文件 /etc/my.cnf

    [mysqld]
    password_require_current=ON  # 启用密码验证
    
  • 动态持久化设置

    SET PERSIST password_require_current = ON;  # 启用
    SET PERSIST password_require_current = OFF; # 禁用
    

3. 单个账户密码验证策略

(1)语法

CREATE | ALTER USER ... PASSWORD REQUIRE CURRENT {OPTIONAL | DEFAULT}
  • CURRENT:需要指定当前密码
  • CURRENT OPTIONAL:不需要指定当前密码
  • CURRENT DEFAULT:使用全局设置(不指定选项时默认为此)

(2)示例

  • 设置需要指定当前密码

    CREATE USER zabbix@localhost PASSWORD REQUIRE CURRENT;
    ALTER USER zabbix@localhost PASSWORD REQUIRE CURRENT;
    
  • 设置不需要指定当前密码

    CREATE USER zabbix@localhost PASSWORD REQUIRE CURRENT OPTIONAL;
    ALTER USER zabbix@localhost PASSWORD REQUIRE CURRENT OPTIONAL;
    
  • 恢复全局验证策略

    CREATE USER zabbix@localhost PASSWORD REQUIRE CURRENT DEFAULT;
    ALTER USER zabbix@localhost PASSWORD REQUIRE CURRENT DEFAULT;
    

4. 修改密码语法及示例

(1)语法

ALTER USER xxx IDENTIFIED BY '新密码' REPLACE '当前密码';

说明:SET PASSWORD 用法类似;需指定当前密码时必须用 REPLACE;仅能为当前账户使用 REPLACE;二进制日志中 REPLACE 会被忽略(避免明文密码记录)。

(2)示例

  • 修改当前账户密码

    ALTER USER user() IDENTIFIED BY 'zabbix1' REPLACE 'zabbix';  # 使用当前账户变量
    ALTER USER u_zabbix@localhost IDENTIFIED BY 'zabbix2' REPLACE 'zabbix1';  # 显式指定当前账户
    

    注意:若修改其他账户密码时使用 REPLACE 会报错:ERROR 3893 (HY000): Do not specify the current password while changing it for other users.

  • 修改当前账户的验证插件和密码(需 CREATE USER 权限)

    ALTER USER u_zabbix@localhost IDENTIFIED WITH caching_sha2_password BY 'zabbix3' REPLACE 'zabbix1';
    

六、双密码支持

1. 作用

允许账户同时拥有主密码和第二密码(辅助密码),避免因密码更改导致服务中断(适用于多服务器复制、多应用连接等场景)。

2. 语法

(1)保留当前密码为第二密码

新密码作为主密码,当前密码变为第二密码;若已有第二密码则替换;新密码为空时第二密码也为空;原密码为空时执行会报错;若同时更改认证插件并指定此语句会报错。
所需权限:APPLICATION_PASSWORD_ADMIN(操作自身账户)、CREATE USER(操作其他账户)。

ALTER USER|SET PASSWORD ... RETAIN CURRENT PASSWORD

(2)删除第二密码(仅保留主密码)

ALTER USER ... DISCARD OLD PASSWORD

3. 查看第二密码

第二密码存储在 mysql.user 表的 User_attributes 列中:

SELECT * FROM mysql.user WHERE user='zabbix'\G

结果中 User_attributes 字段会包含 additional_password(第二密码哈希值)。

4. 配置过程

  1. 主节点设置新密码并保留当前密码为第二密码

    ALTER USER zabbix@localhost IDENTIFIED BY '123' RETAIN CURRENT PASSWORD;
    
  2. 等待从节点密码复制完成

  3. 将复制结构的密码更新为新密码

  4. 丢弃第二密码(旧密码)

    ALTER USER 'appuser1'@'host1.example.com' DISCARD OLD PASSWORD;
    

七、随机生成密码

1. 特点

  • 默认长度为 20 位
  • 存储在 mysql.user 表的 generated_password
  • 二进制日志中记录哈希后的密码(格式:CREATE | ALTER USER ... IDENTIFIED WITH auth_plugin AS 'auth_string'
  • 不受 validate_password 组件策略影响

2. 系统变量

  • generated_random_password_length:控制随机密码长度(范围 5-255,默认 20)

3. 语法及示例

(1)语法

CREATE USER xxx IDENTIFIED BY RANDOM PASSWORD;
ALTER USER xxx IDENTIFIED BY RANDOM PASSWORD;
SET PASSWORD FOR xxx TO RANDOM;

(2)示例

  • 创建用户时生成随机密码

    CREATE USER 
    u1@localhost IDENTIFIED BY RANDOM PASSWORD, 
    u2@localhost IDENTIFIED BY RANDOM PASSWORD, 
    u3@localhost IDENTIFIED BY RANDOM PASSWORD;
    
  • 修改用户密码为随机密码

    ALTER USER 
    u1@localhost IDENTIFIED BY RANDOM PASSWORD, 
    u2@localhost IDENTIFIED BY RANDOM PASSWORD;
    
  • 为指定用户设置随机密码

    SET PASSWORD FOR u3@localhost TO RANDOM;
    

八、登录失败跟踪和临时账户锁定

连续登录失败(密码错误)达到指定次数后,账户会被临时锁定。

1. 语法及选项说明

CREATE USER 用户名@主机 IDENTIFIED BY '密码' 
FAILED_LOGIN_ATTEMPTS N  # 连续 N 次登录失败触发锁定
PASSWORD_LOCK_TIME {N | UNBOUNDED};  # 锁定时间(N 天,0 禁用;UNBOUNDED 表示永久锁定)

示例:

CREATE USER u1@localhost IDENTIFIED BY 'u1' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3;  # 3 次失败锁定 3 天
CREATE USER u2@localhost IDENTIFIED BY 'u2' FAILED_LOGIN_ATTEMPTS 4 PASSWORD_LOCK_TIME UNBOUNDED;  # 4 次失败永久锁定

2. 特点

  • FAILED_LOGIN_ATTEMPTSPASSWORD_LOCK_TIME 必须非 0(未指定时默认 0,即不启用)
  • 仅连续失败计数,中间成功登录会重置计数
  • 锁定后无法登录,需解锁后才能使用
  • 代理用户登录失败时,跟踪的是代理用户而非被代理用户

3. 重置账户状态(解除锁定)

  • 全局重置:服务器重启或执行 FLUSH PRIVILEGES;

  • 单个账户重置:

    • 等待锁定时间结束

    • 重新设置失败次数和锁定时间

      ALTER USER u1@localhost FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 3;
      
    • 直接解锁

      ALTER USER u1@localhost ACCOUNT UNLOCK;