SQL Server 登入 'xxx' 登入失敗。此登入的密碼已經逾期。
(英文錯誤訊息是:Login failed for SQL Server login 'xxx'. The password for this login has expired. )
第一次看到這樣的訊息,不禁皺了一下眉頭,錯誤訊息指出的登入 (Login),是前不久為了減少網站存取資料庫的安全性議題所新增的 (僅賦予讀取權限),也讓我想起當初建立這個登入是直接下 T-SQL 指令:CREATE LOGIN 去做,難不成有甚麼細節疏忽了,造成登入密碼逾期的錯誤?在一邊查看 MSDN 說明文件,一邊回憶推敲之下,判斷應該是為了要在初次登入時讓 SQL Server 提醒使用者變更密碼,因此 Create Login 的語法是這麼下的:
WITH PASSWORD = 'P@ssw0rd' MUST_CHANGE,
CHECK_POLICY = ON,
CHECK_EXPIRATION = ON
GO
原因在 MSDN 說明文件有提到:
如果指定 MUST_CHANGE,則 CHECK_EXPIRATION 和 CHECK_POLICY 必須設為 ON。否則,陳述式便會失敗。這下可好了…,使用者初次登入確實會彈出視窗要求變更密碼,請見下圖:
但可想而知,密碼變更完畢,強制執行密碼逾期原則 (CHECK_EXPIRATION) 依然是啟用狀態…
所幸問題不大,只要把強制執行密碼逾期勾選拿掉,系統就可以恢復正常運作。
平心而論,這事件算是自己不小心吧,不過卻也讓我有些額外收穫…,請參考 SQL Server 的安全性考量 - 密碼原則,當 SQL Server 2005 是在 Windows Server 2003 或更新版本上執行時,就可以使用 Windows 密碼原則機制,包含密碼(複雜性)原則、過期原則,前者是盡量使用長且複雜的密碼以防範暴力破解,後者則是管理密碼的壽命以強制定期更換密碼。也就是說,考慮到安全性,這兩個選項都應該勾選,但問題來了,針對「強制執行密碼逾期」這選項,MSDN 文件有一段話是這麼說的:
密碼過期原則用於管理密碼的壽命。當 SQL Server 2005 強制執行密碼過期原則時,系統會提醒使用者變更舊密碼和停用有過期密碼的帳戶。事實上經實驗證明,提醒使用者變更密碼的情況,僅發生在你是用 SSMS 等 GUI 連線工具時,萬一你跟我一樣把這樣的登入帳號用在 ASP.NET 的連線字串時,一旦密碼過期了,網站是直接掛給你看…。
那有沒有可能在即將過期之前發送個通知呢?答案是肯定的!請參考以下語法:
-- 查詢設定密碼逾期的登入帳號
SELECT @login = name
FROM sys.sql_logins
WHERE (type = 's') AND (is_expiration_checked = 1)
-- 計算登入帳號密碼已使用天數
SELECT @login AS 'login',
DATEDIFF(d, CAST(LOGINPROPERTY(@login, 'PasswordLastSetTime') AS datetime), GETDATE()) AS 'pwd_using_days'
/*
-- 傳回密碼到期之前的剩餘天數
-- CAUTION : For SQL Server 2008 ONLY!
SELECT LOGINPROPERTY(@login, 'DaysUntilExpiration') AS 'days_until_expiration'
*/
以上只是簡示如何計算已使用天數,有需要的人請自行擴充,可以做到逐一計算有設定密碼逾期的登入,使用達到一定天數後,配合 Database Mail 發送通知信以便提醒更改密碼。
參考資料:
- CREATE LOGIN (Transact-SQL)
- SQL Server 的安全性考量 - 密碼原則
- 安全性目錄檢視 - sys.sql_logins (Transact-SQL)
- LOGINPROPERTY (Transact-SQL)
- Database Mail