春天记住我与额外的登录参数



在春季 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)
}

最新更新