背景
客戶反饋MySQL賬號已經(jīng)設(shè)置成密碼永不過期了,但是在登錄后總是提示報(bào)錯(cuò)
ERROR 1862 (HY000): Your password has expired. To log in you must change it using a client that supports expired passwords.
排查方法
首先檢查一下MySQL服務(wù)器設(shè)置的密碼過期時(shí)間,可以看到默認(rèn)密碼60天就會過期
mysql> show variables like '%lifetime%';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| default_password_lifetime | 60 |
+---------------------------+-------+
1 row in set (0.01 sec)
然后檢查一下mysql.user表,看看用戶說提示報(bào)錯(cuò)的賬號的配置
mysql> select user,host,password_expired,password_last_changed,password_lifetime from mysql.user where user='user';
+------+------+------------------+-----------------------+-------------------+
| user | host | password_expired | password_last_changed | password_lifetime |
+------+------+------------------+-----------------------+-------------------+
| user | % | N | 2023-02-06 15:03:41 | 0 |
+------+------+------------------+-----------------------+-------------------+
1 row in set (0.00 sec)
-
password_expired列為N
這個(gè)賬號沒有被手動設(shè)置密碼過期 -
password_lifetime列為0
賬號正常應(yīng)該已經(jīng)設(shè)置成密碼永不過期了 -
password_last_changed列為2023-02-06 15:03:41
上次密碼修改時(shí)間是2023-02-06
疑點(diǎn)
這個(gè)問題詭異的地方就是password_lifetime列為0。
正常情況下,單個(gè)賬號的策略會覆蓋全局策略。也就是說,如果設(shè)置過單個(gè)賬號密碼永不過期,就不會再參考default_password_lifetime參數(shù)值計(jì)算密碼過期時(shí)間。
這個(gè)賬號如果按照上次密碼修改時(shí)間+默認(rèn)60天過期計(jì)算的話,確認(rèn)是密碼過期該修改密碼了。
分析
排查了半天,后來靈機(jī)一動,想起來一種情況:
這個(gè)賬號是客戶自己設(shè)置成密碼永不過期的,正常我們設(shè)置密碼永不過期都是使用ALTER USER user PASSWORD EXPIRE NEVER語句,但是客戶會不會用了其他方法呢,比如說直接修改mysql.user表?
我們知道,MySQL會在啟動時(shí)將權(quán)限表讀取到內(nèi)存中。而直接更新mysql.user表,不會立即生效,需要再執(zhí)行FLUSH PRIVILEGES重新加載權(quán)限表。
后來追問客戶,客戶果然是在navicat界面中直接點(diǎn)擊mysql.user表,把password_lifetime列改為0,就以為設(shè)置成功了。
處理方案
執(zhí)行FLUSH PRIVILEGES刷新權(quán)限后,果然賬號登錄時(shí)不再報(bào)錯(cuò)。
原因
設(shè)置密碼永不過期的方法錯(cuò)誤,只更新了mysql.user表,沒有刷新權(quán)限
正確方法
ALTER USER user PASSWORD EXPIRE NEVER;
-- 或者
UPDATE mysql.user SET password_lifetime=0 WHERE user='user';
FLUSH PRIVILEGES;
擴(kuò)展知識
MySQL的權(quán)限修改何時(shí)生效
MySQL在啟動時(shí)將權(quán)限表加載到內(nèi)存中,之后使用內(nèi)存中的權(quán)限表進(jìn)行訪問控制
- 使用賬號管理語句,如
ALTER USER/GRANT/REVOKE/SET PASSWORD等,會重新加載權(quán)限表,立即生效。 - 使用
INSERT,UPDATE,DELETE等更改權(quán)限表,不會加載到內(nèi)存中,不會立即生效。要使這些更改生效,可以:- 重新加載權(quán)限表
FLUSH PRIVILEGES - 重啟數(shù)據(jù)庫
- 重新加載權(quán)限表
設(shè)置密碼有效期策略
- 全局有效期更改
SET GLOBAL default_password_lifetime = 60
- 單個(gè)賬號有效期更改
-- 跟隨全局策略
ALTER USER user PASSWORD EXPIRE DEFAULT
-- 密碼永不過期
ALTER USER user PASSWORD EXPIRE NEVER
-- 密碼N天過期
ALTER USER user PASSWORD EXPIRE INTERVAL N DAY
- 直接設(shè)置密碼過期
ALTER USER user PASSWORD EXPIRE
密碼立刻過期,在賬號登錄后,必須修改密碼才能進(jìn)行其他操作
使用這種方式設(shè)置密碼過期后,沒有SQL語句直接設(shè)置密碼不過期,但是可以通過更新mysql.user的password_expired列,然后FLUSH PRIVILEGES刷新權(quán)限,變相允許用戶繼續(xù)使用之前的密碼