java - 如何在注销时使“记住我”失效?

标签 java spring-mvc spring-security

好吧,我没有实现PersistentTokenBasedRememberMeServices,因此我无法使用.logout(request, response, auth)。但我使用 JdbcTokenRepositoryImpl 是为了使用 PersistentTokenRepository 来实现记住我功能。

注销 Controller :

@Controller
public class LogoutController {

    @RequestMapping(value = {"/logout"}, method = RequestMethod.GET)
    public String logout() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if(auth != null) {
            SecurityContextHolder.getContext().setAuthentication(null);
        }

        return "redirect:/login?logout";
    }
}

安全配置:

@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/", "/playground").hasAnyRole("ROOT", "MODER", "USER")
            .antMatchers("/users/**").hasAnyRole("ROOT", "MODER")
        .and()
            .formLogin().loginPage("/login").loginProcessingUrl("/login").failureHandler(customAuthenticationFailureHandler())
        .and()
            .rememberMe().rememberMeParameter("remember-me").tokenRepository(persistentTokenRepository()).userDetailsService(userDetailsService)
        .and()
            .logout().logoutUrl("/logout");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setPasswordEncoder(passwordEncoder());
        authProvider.setUserDetailsService(userDetailsService);
        return authProvider;
    }

    @Bean
    public AuthenticationFailureHandler customAuthenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;
    }

当我使用 Remember-me 登录时,我无法注销。我想是因为记住我的功能。我应该向 LogoutController 添加什么才能进行正确的注销过程?

注意:问题是,如果我在注销时仅使用 POST 方法,那么它完全可以工作,但我想使用 GET 方法,因此我必须创建一个注销 Controller 来执行get方法。

最佳答案

尝试禁用 crsf (http.csrf().disable())。

spring安全注销过滤器的默认实现是:

        if (http.getConfigurer(CsrfConfigurer.class) != null) {
            this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
        }
        else {
            this.logoutRequestMatcher = new OrRequestMatcher(
                new AntPathRequestMatcher(this.logoutUrl, "GET"),
                new AntPathRequestMatcher(this.logoutUrl, "POST"),
                new AntPathRequestMatcher(this.logoutUrl, "PUT"),
                new AntPathRequestMatcher(this.logoutUrl, "DELETE")
            );
        }

如您所见,如果您的 Csrf 已启用(默认情况下,即使您覆盖 protected void configure(HttpSecurity http) 也会启用它),那么只有 POST 方法才有效,如果不是全部都工作的话。

顺便说一句:您确定您的请求到达了LogoutController,因为我认为它使用标准的 Spring Security 注销机制? (要禁用它,请执行http.logout().disable(),与默认情况下启用的csrf相同)

关于java - 如何在注销时使“记住我”失效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54105993/

相关文章:

Java 摘要式身份验证 POST XML

java - Ejb,第二个方法中的错误回滚第一个方法

java - Spring security 登录后如何跳转到另一个页面

facebook - Spring social ConnectController/connect/facebook 给出 404 错误

java - Reducer 获得的记录少于预期

Java中Asterisk如何拨号

Spring 3 MVC : is it possible to have a spring form without 'commandName' binding?

android - 如何从可以输入 Spring Security 安全 Web 服务方法的 Android 应用发出请求?

spring - Keycloak角色映射

tomcat - 有没有办法在 spring-security 中强制某些页面使用 https?