在春季 mvc 应用程序中,我在登录屏幕上捕获了一个额外的"位置"参数,并使用它进行身份验证以及用户名。所以在'loadUserByUsername'中,我的sql查询是这样的,
select from user where username = ? and location = ?
现在,如果用户是记住我的用户,则无法捕获"位置"参数,因为不会有登录提示。在记住我功能的情况下,春天只在cookie中存储用户名。对于记住我登录,它会从cookie中检索该用户名,并将其传递给"loadUserByUsername"调用以从DB加载用户。因此,就我而言,对于记住我的用户,由于"位置"为空查询以加载用户失败。
我想知道是否有办法覆盖默认的 spring 行为并将"位置"与用户名一起存储在 cookie 中,然后将位置和用户名传递给 PersistentTokenBasedRememberMeServices.processAutoLoginCookie() 中的"loadUserByUsername"。
请参阅下面的代码以供参考,
自定义身份验证过滤器.java :-
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
final Long locationId = Long.parseLong(request.getParameter("locations"));
request.getSession().setAttribute("LOCATION_ID", locationId);
return super.attemptAuthentication(request, response);
}
}
安全配置.java:-
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DataSource dataSource;
@Autowired
private AuthenticationManagerBuilder auth;
@Autowired
public void configureGlobal(UserDetailsService userDetailsService, AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
AccessDeniedExceptionHandler accessDeniedExceptionHandler;
@Bean
public CustomInvalidSessionStrategy invalidSessionStrategy() {
return new CustomInvalidSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/error/**").permitAll()
.antMatchers("/secured/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
// .defaultSuccessUrl("/")
.permitAll()
.and().rememberMe().rememberMeServices(persistentTokenBasedRememberMeServices())
.and()
.logout()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedExceptionHandler);
http.addFilterBefore(customAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
http.addFilterAfter(rememberMeAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() {
AuthenticationManager manager = null;
try {
manager = super.authenticationManagerBean();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return manager;
}
@Bean
public SimpleUrlAuthenticationSuccessHandler simpleUrlAuthenticationSuccessHandler() {
SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler();
handler.setDefaultTargetUrl("/");
return handler;
}
@Bean
public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler();
handler.setDefaultFailureUrl("/login?error");
return handler;
}
@Bean
public CustomAuthenticationFilter customAuthenticationFilter () {
CustomAuthenticationFilter filter= new CustomAuthenticationFilter();
filter.setRequiresAuthenticationRequestMatcher(
new AntPathRequestMatcher("/login","POST"));
filter.setAuthenticationManager(authenticationManagerBean());
filter.setUsernameParameter("username");
filter.setPasswordParameter("password");
filter.setAuthenticationSuccessHandler(simpleUrlAuthenticationSuccessHandler());
filter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler());
filter.setRememberMeServices(persistentTokenBasedRememberMeServices());
return filter;
}
@Bean
public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() {
RememberMeAuthenticationFilter filter = new RememberMeAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setRememberMeServices(persistentTokenBasedRememberMeServices());
return filter;
}
@Bean
public PersistentTokenBasedRememberMeServices persistentTokenBasedRememberMeServices() {
PersistentTokenBasedRememberMeServices service = new PersistentTokenBasedRememberMeServices("remember_me_key", userDetailsService, persistentTokenRepository());
service.setCookieName("remember_me");
service.setTokenValiditySeconds(864000);
return service;
}
@Autowired
public UserDetailsService userDetailsService;
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(dataSource);
return tokenRepositoryImpl;
}
}
扩展类 PersistentTokenBasedRememberMeServices 并覆盖其方法,如下所示
@Override
processAutoLoginCookie(String[] cookieTokens,HttpServletRequest request, HttpServletResponse response){
super.processAutoLoginCookie(cookieTokens,request,response); // do not provide any implementation to loadUserByUsername() in your CustomUserDetail and add one more method loadUserbyUsenameAndLocation(username, location);
String location = request.getSession().getAttribute("LOCATION_ID");
return ((customeUserDetailsService)userDetailsService).loadUserbyUsenameAndLocation(username, location)
}