添加记住我功能
- 记住我功能基本原理
- 实现记住我功能
- 记住我SpringSecurity源码分析
1.记住我功能基本原理
过滤器链
2.实现记住我功能
给登录界面添加记住我选项
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h2>标准登录页面</h2>
<h3>表单登录</h3>
<form action="/authentication/form" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>图形验证码:</td>
<td>
<input type="text" name="imageCode">
<img src="/captcha/image">
</td>
</tr>
<tr>
<td colspan="2"><input type="checkbox" name="remember-me" value="true"/>记住我</td>
</tr>
<tr>
<td colspan="2">
<button type="submit">登录</button>
</td>
</tr>
</table>
</form>
</body>
</html>
注意记住我的name要固定 源码如下:
public final class RememberMeConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<RememberMeConfigurer<H>, H> { /** * The default name for remember me parameter name and remember me cookie name */ private static final String DEFAULT_REMEMBER_ME_NAME = "remember-me"; }
浏览器配置中添加可配置的失效时间
package com.rui.tiger.auth.core.properties;
import com.rui.tiger.auth.core.model.enums.LoginTypeEnum;
/**
* 浏览器配置
*
* @author CaiRui
* @date 2018-12-6 8:42
*/
public class BrowserProperties {
/**
* 登录页面 不配置默认标准登录界面
*/
private String loginPage = "/tiger-login.html";
/**
* 跳转类型 默认返回json数据
*/
private LoginTypeEnum loginType = LoginTypeEnum.JSON;
/**
* 记住我秒数
* @return
*/
private int remberMeSeconds=3600;
public String getLoginPage() {
return loginPage;
}
public void setLoginPage(String loginPage) {
this.loginPage = loginPage;
}
public LoginTypeEnum getLoginType() {
return loginType;
}
public void setLoginType(LoginTypeEnum loginType) {
this.loginType = loginType;
}
public int getRemberMeSeconds() {
return remberMeSeconds;
}
public void setRemberMeSeconds(int remberMeSeconds) {
this.remberMeSeconds = remberMeSeconds;
}
}
依据记住我原理对配置类进行修改
package com.rui.tiger.auth.browser.config;
import com.rui.tiger.auth.core.authentication.TigerAuthenticationFailureHandler;
import com.rui.tiger.auth.core.authentication.TigerAuthenticationSuccessHandler;
import com.rui.tiger.auth.core.captcha.CaptchaFilter;
import com.rui.tiger.auth.core.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
/**
* 浏览器security配置类
*
* @author CaiRui
* @date 2018-12-4 8:41
*/
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityProperties securityProperties;
@Autowired
private TigerAuthenticationFailureHandler tigerAuthenticationFailureHandler;
@Autowired
private TigerAuthenticationSuccessHandler tigerAuthenticationSuccessHandler;
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsService userDetailsService;
/**
* 密码加密解密
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 记住我持久化数据源
* JdbcTokenRepositoryImpl CREATE_TABLE_SQL 建表语句可以先在数据库中执行
*
* @return
*/
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//第一次会执行CREATE_TABLE_SQL建表语句 后续会报错 可以关掉
//jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//加入图片验证码过滤器
CaptchaFilter captchaFilter = new CaptchaFilter();
captchaFilter.setFailureHandler(tigerAuthenticationFailureHandler);
captchaFilter.setSecurityProperties(securityProperties);
captchaFilter.afterPropertiesSet();
//图片验证码放在认证之前
http.addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
.formLogin()
.loginPage("/authentication/require")//自定义登录请求
.loginProcessingUrl("/authentication/form")//自定义登录表单请求
.successHandler(tigerAuthenticationSuccessHandler)
.failureHandler(tigerAuthenticationFailureHandler)
.and()
//记住我相关配置
.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(securityProperties.getBrowser().getRemberMeSeconds())
.userDetailsService(userDetailsService)
.and()
.authorizeRequests()
.antMatchers(securityProperties.getBrowser().getLoginPage(),
"/authentication/require", "/captcha/image")//此路径放行 否则会陷入死循环
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable()//跨域关闭
;
}
}
下面我们来测试下,项目启动后可以看到用户token关系表已经建好了
我们再前面登录,勾选记住我功能
成功登录后,可以看见后台已经保存关系了
再访问我们的用户信息可以成功访问,接下来我们退出浏览器或重新启动项目,再次访问用户信息 还是可以成功访问 说明我们的记住我功能成功实现
3.记住我SpringSecurity源码分析