今天在学习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,有时候这个配置是多余,如果配置了需要删除