原理
增加配置
BrowserPropertiescom.imooc.security.core.properties.BrowserProperties
package com.imooc.security.core.properties;
/**
* @Author:LovingLiu
* @Description:
* @Date:Created in 2019-12-22
*/
public class BrowserProperties {
private String loginPage = "/imooc-signIn.html"; // 指定默认跳转页面
private LoginType loginType = LoginType.JSON; // 指定登录方式
private int rememberMeSeconds = 3600; // 记住我的有效期
public String getLoginPage() {
return loginPage;
}
public void setLoginPage(String loginPage) {
this.loginPage = loginPage;
}
public LoginType getLoginType() {
return loginType;
}
public void setLoginType(LoginType loginType) {
this.loginType = loginType;
}
public int getRememberMeSeconds() {
return rememberMeSeconds;
}
public void setRememberMeSeconds(int rememberMeSeconds) {
this.rememberMeSeconds = rememberMeSeconds;
}
}
修改配置类BrowserSecurityConfig
com.imooc.security.browser.BrowserSecurityConfig
package com.imooc.security.browser;
import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.ValidateCodeFilter;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
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;
/**
* @Author:LovingLiu
* @Description: Security安全配置的适配器
* @Date:Created in 2019-12-18
*/
@Configuration
@EnableWebSecurity
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityProperties securityProperties;
@Autowired
private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler imoocAuthenticationFailureHandler;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(); // 推荐使用 BCrypt 的加密的形式
}
@Autowired
private DataSource dataSource;
@Autowired
private MyUserDetailService userDetailService;
@Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
// tokenRepository.setCreateTableOnStartup(true); // 系统启动时自动创建表(仅仅限制第一次系统启动,启动一次之后注解掉)
return tokenRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
validateCodeFilter.setAuthenticationFailureHandler(imoocAuthenticationFailureHandler);
validateCodeFilter.setSecurityProperties(securityProperties);
validateCodeFilter.afterPropertiesSet(); // 设置配置的属性
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class). // 添加自定义过滤器
formLogin(). // 声明验证方式为表单登录
loginPage("/authentication/require"). // 自定义登录界面
loginProcessingUrl("/authentication/form"). // 指定接收username/password的请求路径
successHandler(imoocAuthenticationSuccessHandler). // 使用自定义成功处理器
failureHandler(imoocAuthenticationFailureHandler). // 使用自定义失败处理器
and(). //
rememberMe().
tokenRepository(persistentTokenRepository()). // 返回jdbcTokenRepository的实现
tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds()). // 配置有效时间
userDetailsService(userDetailService). // 使用声明的用户
and().
authorizeRequests(). // 对请求进行授权
antMatchers("/authentication/require","/authentication/form","/code/image",securityProperties.getBrowser().getLoginPage()).permitAll().// 配置不进行认证请求
anyRequest(). // 任意请求
authenticated(). // 都需要身份认证
and().
csrf().disable(); // 关闭跨站请求防护
}
}
Filter 执行顺序
RememberMeAuthenticationFilter在过滤器链中的执行顺序
1.1
UsernamePasswordAuthenticationFilter接受到认证请求当认证成功后,会调用一个叫做
RemeberMeService的服务,这个是SpringSecurity提供的服务,它主要做两件事情,生成一个Token,然后分别写入数据库和Cookie中去,如下图代码所示:
源码
1.2第二次服务请求
此时是有RememberMeAuthenticationFilter来处理该请求(前提:其他过滤器放行),Filter会读取Cookie中的Token,然后继续由RemeberMeService的TokenRepository来查找数据库中的相关信息,如果查询到了,此时会调用UserDetailsService来获取用户信息。RememberMeAuthenticationFilter所处的位置是在倒数第二个Filter的位置。只要前面的Filter过滤掉了,都会经过它来判断是否需要免密登录。













网友评论