Spring Security 6 中使用 securityMatcher 时默认 /logout 不起作用

问题描述 投票:0回答:1

在 Spring Security 6 中(特别是 Spring Boot 3.2,在我的例子中是带有 Thymeleaf 的 Spring MVC),当使用 securityMatcher 时,默认的 /logout POST 或 GET 将停止工作。

    @Bean
    public SecurityFilterChain openFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher("/EParticipate/baudit/**")
            .addFilterBefore(new BauditUsernamePasswordAuthenticationFilter(
                this.authenticationManager(userDetailsService, passwordEncoder())),
                UsernamePasswordAuthenticationFilter.class
            )
            .authorizeHttpRequests((requests) -> requests
                .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
                .requestMatchers("/EParticipate/baudit/**").hasRole("BAUDIT")
                .requestMatchers("/EParticipateSecurity/**").permitAll()
            )
            .authenticationManager(this.authenticationManager(userDetailsService, passwordEncoder()))
            .formLogin(form -> form
                .loginPage("/EParticipateSecurity/login_request").permitAll()
                .defaultSuccessUrl("/EParticipate/baudit")
            )
        return http.build();
    }

以及 Thymeleaf 中的 POST 链接:

    <form id="logout_form" th:action="@{/logout}" method="POST">
         <button id="logout_button" type="submit">Logout</button>
    </form>

即使你在requestMatcher中添加了

permitAll()
,它仍然不起作用:

    @Bean
    public SecurityFilterChain openFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher("/EParticipate/baudit/**")
            .addFilterBefore(new BauditUsernamePasswordAuthenticationFilter(
                this.authenticationManager(userDetailsService, passwordEncoder())),
                UsernamePasswordAuthenticationFilter.class
            )
            .authorizeHttpRequests((requests) -> requests
                .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
                .requestMatchers("/EParticipate/baudit/**").hasRole("BAUDIT")
                //Doesn't work
                .requestMatchers("/EParticipateSecurity/**","/logout").permitAll()
            )
            .authenticationManager(this.authenticationManager(userDetailsService, passwordEncoder()))
            .formLogin(form -> form
                .loginPage("/EParticipateSecurity/login_request").permitAll()
                .defaultSuccessUrl("/EParticipate/baudit")
            )
        return http.build();
    }
spring-boot spring-mvc spring-security
1个回答
0
投票

为了解决这个问题,我必须在 securityMatcher 的 URL 下添加一个自定义注销作为子 URL(我还添加了一个注销处理程序以确保注销时清除所有内容)。

@Bean
public SecurityFilterChain openFilterChain(HttpSecurity http) throws Exception {
    http.securityMatcher("/EParticipate/baudit/**")
        .addFilterBefore(new BauditUsernamePasswordAuthenticationFilter(
            this.authenticationManager(userDetailsService, passwordEncoder())),
        UsernamePasswordAuthenticationFilter.class
        )
        .authorizeHttpRequests((requests) -> requests
            .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
            .requestMatchers("/EParticipate/baudit/**").hasRole("BAUDIT")
            .requestMatchers("/EParticipateSecurity/**").permitAll()
        )
        .authenticationManager(this.authenticationManager(userDetailsService, passwordEncoder()))
        .formLogin(form -> form
            .loginPage("/EParticipateSecurity/login_request").permitAll()
            .defaultSuccessUrl("/EParticipate/baudit")
        )
        .logout((logout) -> logout
            .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(Directive.CACHE,Directive.COOKIES,Directive.EXECUTION_CONTEXTS,Directive.STORAGE)))
            .logoutUrl("/EParticipate/baudit/logout")//URL under the securityMatcher URL above
            .logoutSuccessUrl("/EParticipateSecurity/login_request").permitAll()
        );
    return http.build();
}
© www.soinside.com 2019 - 2024. All rights reserved.