几个 AntPathRequestMatcher 的 SecurityConfiguration / RequestMatcher 问题

SecurityConfiguration / RequestMatcher issue with several AntPathRequestMatcher

我刚刚在我的 spring 引导 API 中添加了令牌身份验证,它运行良好,只有一个问题。

我想使用 /login 端点(带有登录名和密码)获取令牌,然后在 header 中将其传递给所有需要身份验证的服务,即 logout以及 /api/** 路线上的所有内容。

我的问题是我必须让 /login 不受保护,但 logout 不能,但是我无法删除以下代码中标记为 // TODO Why can't I remove this 的行,否则我会得到一个使用或不使用令牌

访问 /logout 时出现 403 错误(禁止访问)

我不明白为什么,我认为这可能与我的 RequestMacther 有关:

private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/api/**"),
            new AntPathRequestMatcher("/logout/**")
    );

然而 /logout 确实需要使用令牌进行身份验证,所以可能不是那样。

TLDR 使用此代码一切正常,但我想删除 // TODO Why can't I remove this 之后的行,但如果我删除它

,我会在 /logout 上收到 403

感谢任何帮助。

我的安全配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@AllArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/api/**"),
            new AntPathRequestMatcher("/logout/**")
    );

    AuthenticationProvider provider;

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(provider);
    }

    @Override
    public void configure(final WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers("/login/**");
        // TODO Why can't I remove this
        webSecurity.ignoring().antMatchers("/logout/**");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling()
                .and()
                .authenticationProvider(provider)
                .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(PROTECTED_URLS)
                .authenticated()
                .and()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();
    }

    @Bean
    AuthenticationFilter authenticationFilter() throws Exception {
        final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }

    @Bean
    AuthenticationEntryPoint forbiddenEntryPoint() {
        return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
    }
}

你可以在方法configure(HttpSecurity http)中配置它,只需添加

http.authorizeRequests().antMatchers("/login").permitAll();
http.authorizeRequests().antMatchers("/logout").permitAll();

所以我找到了如何让它工作,似乎有 two/three 个问题:

  • 我删除了 .csrf().disable(),因为这似乎不是一个好的做法,但实际上这会导致一些问题
  • configure(HttpSecurity http) 函数中语句的顺序很重要,将 logout() 放在最后显然是有问题的
  • 删除了一些不需要的代码,这些代码可能会或可能不会导致问题。

最后是我的作品SecurityConfiguration:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@AllArgsConstructor
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/api/**"),
            new AntPathRequestMatcher("/logout/**")
    );

    AuthenticationProvider provider;

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(provider);
    }

    @Override
    public void configure(final WebSecurity webSecurity) {
        webSecurity.ignoring().antMatchers("/login/**");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable()
                .logout().disable()
                .exceptionHandling()
                .and()
                .authenticationProvider(provider)
                .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(PROTECTED_URLS)
                .authenticated()
                .and();
    }

    @Bean
    AuthenticationFilter authenticationFilter() throws Exception {
        final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }
}