今天在學習Spring Security 自動登錄時遇到了MySQL數據庫的時區問題,在網上找了很多資料都不能很好的解決問題,不過,最終問題被我解決,特此記錄,希望能幫助到你(解決思路請直接看文章末尾)
在實現自動登錄功能的時候,Spring Security默認是依賴一張 persistent_logins 表的,此表的建表語句如下:
CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
其中 last_used 字段是 timestamp 格式的,當我進行自動登錄的時候發現存入數據庫的值是這樣的

我的mysql服務器系統時間是這樣的

系統時間是正確的,但是卻相差8小時,直接在服務器登錄mysql進行查詢,結果是這樣的

查看時區設置

隨后檢查jdbc連接配置,當時配置是這樣的(請記住紅色框框的配置,這里才是問題重點)

看上去配置的連接也沒有問題,然后我就在本地寫了個單元測試來查詢persistent_logins表的數據,看看程序讀出來的時間有沒有問題

通過 SimpleDateFormat打印的時間是沒有問題的,但是mybatis的SQL日志里時間是有問題的
通過這一些列的查詢可以發現:
- 系統默認時間沒有問題
- MySQL的時間是有問題的,與服務器對不上
- 程序通過jdbc連接配置,強行糾正了時區,但並未改變數據庫存儲的時間值
作為一個嚴謹的程序員,我們當然要從根源上解決問題,因此首先要改的就是MySQL的時區設置,為了一勞永逸,我直接修改MySQL的配置文件,在Linux系統中,MySQL配置文件的默認位置如下:
/etc/my.cnf
在配置文件的[mysqld]模塊添加如下配置,然后重啟MySQL服務
default_time_zone='+8:00'
刪除persistent_logins表原來的數據,重新進行自動登錄操作,查看數據如下:

登錄MySQL查看時間如下:

再跑單元測試,查詢的時間如下:

MySQL時區是沒有問題的,但是存入和查詢的數據卻是不正確的,這時我就開始懷疑是不是連接配置的問題了,我先試着將jdbc的時區配置去掉,刪除如下配置
&serverTimezone=GMT
清空數據庫,再來一次,重啟應用程序,模擬自動登錄,然后查看數據庫數據如下:

終於,數據庫存入的時間值正確了,然后再跑單元測試看一下查詢的數據結果

同樣沒有問題 ,在看MySQL服務

同樣沒有問題,至此,時區問題算是徹底解決了,
最后總結:如果你在項目中出現了MySQL時區問題,首先看下MySQL的時區配置是否正確,如果時區沒有問題,則需要查看jdbc連接配置是否配置了serverTimezone,有時候這個配置是多余,如果配置了需要刪除
