记住我
我们的网站还有一个重要的功能,就是记住我,也就是说我们可以在登陆之后的一段时间内,无需再次输入账号和密码进行登陆,相当于服务端已经记住当前用户,再次访问时就可以免登陆进入,这是一个非常常用的功能。
我们之前在JavaWeb阶段,使用本地Cookie存储的方式实现了记住我功能,但是这种方式并不安全,同时在代码编写上也比较麻烦,那么能否有一种更加高效的记住我功能实现呢?
SpringSecurity为我们提供了一种优秀的实现,它为每个已经登陆的浏览器分配一个携带Token的Cookie,并且此Cookie默认会被保留14天,只要我们不清理浏览器的Cookie,那么下次携带此Cookie访问服务器将无需登陆,直接继续使用之前登陆的身份,这样显然比我们之前的写法更加简便。并且我们需要进行简单配置,即可开启记住我功能:
.and()
.rememberMe() //开启记住我功能
.rememberMeParameter("remember") //登陆请求表单中需要携带的参数,如果携带,那么本次登陆会被记住
.tokenRepository(new InMemoryTokenRepositoryImpl()) //这里使用的是直接在内存中保存的TokenRepository实现
//TokenRepository有很多种实现,InMemoryTokenRepositoryImpl直接基于Map实现的,缺点就是占内存、服务器重启后记住我功能将失效
//后面我们还会讲解如何使用数据库来持久化保存Token信息
接着我们需要在前端修改一下记住我勾选框的名称,将名称修改与上面一致,如果上面没有配置名称,那么默认使用"remember-me"作为名称:
<input type="checkbox" name="remember" class="ad-checkbox">
现在我们启动服务器,在登陆时勾选记住我勾选框,观察Cookie的变化。
虽然现在已经可以实现记住我功能了,但是还有一定的缺陷,如果服务器重新启动(因为Token信息全部存在HashMap中,也就是存在内存中),那么所有记录的Token信息将全部丢失,这时即使浏览器携带了之前的Token也无法恢复之前登陆的身份。
我们可以将Token信息记录全部存放到数据库中(学习了Redis之后还可以放到Redis服务器中)利用数据库的持久化存储机制,即使服务器重新启动,所有的Token信息也不会丢失,配置数据库存储也很简单:
@Resource
PersistentTokenRepository repository;
@Bean
public PersistentTokenRepository jdbcRepository(@Autowired DataSource dataSource){
JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl(); //使用基于JDBC的实现
repository.setDataSource(dataSource); //配置数据源
repository.setCreateTableOnStartup(true); //启动时自动创建用于存储Token的表(建议第一次启动之后删除该行)
return repository;
}
.and()
.rememberMe()
.rememberMeParameter("remember")
.tokenRepository(repository)
.tokenValiditySeconds(60 * 60 * 24 * 7) //Token的有效时间(秒)默认为14天
稍后服务器启动我们可以观察一下数据库,如果出现名为persistent_logins
的表,那么证明配置没有问题。
当我们登陆并勾选了记住我之后,那么数据库中会新增一条Token记录。