【问题标题】:Both matchers fit, how to avoid filter being applied? [duplicate]两个匹配器都适合,如何避免应用过滤器? [复制]
【发布时间】:2020-12-05 16:49:58
【问题描述】:

这是我当前的安全配置;如您所见,我为/api/** 提供了一个AntPathRequestMatcher,它应该为基于令牌的安全性应用过滤器;我的身份验证 URL 位于 /api/token 下,显然不应受到保护。当前的.permitAll 似乎被忽略了;我该如何解决这个问题?

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


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

    private static final RequestMatcher FREE_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/api/token")
    );

    @Autowired
    AuthenticationProvider provider;

    public SecurityConfiguration(final AuthenticationProvider authenticationProvider) {
        super();
        this.provider = authenticationProvider;
    }

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

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .exceptionHandling()
                .and()
            .authorizeRequests()
                .requestMatchers(FREE_URLS).permitAll()
                .and()
            .authenticationProvider(provider)
                .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
            .authorizeRequests()
                .requestMatchers(PROTECTED_URLS).authenticated()
                .and()
            .csrf().disable()
            .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);
    }
}

编辑: 这是我的过滤器:它可能真的是这个“抛出新的 AuthenticationCredentialsNotFoundException”,但我不知道如何解决这个问题。难道不应该只更改过滤器链配置吗?过滤器应仅适用于 PROTECTED_URLS 中列出的那些 URL,但被 FREE_URLS 排除的 URL 除外。如果我要更改过滤器,是否不需要告诉过滤器免费 URL?

public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    AuthenticationFilter(final RequestMatcher requiresAuth) {
        super(requiresAuth);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
        String token= httpServletRequest.getHeader(AUTHORIZATION);
        if(token==null) throw new AuthenticationCredentialsNotFoundException("Kein Token im Header angegeben");
        token = StringUtils.removeStart(token, "Bearer").trim();
        Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token, token);
        return getAuthenticationManager().authenticate(requestAuthentication);

    }

    @Override
    protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain, final Authentication authResult) throws IOException, ServletException {
        SecurityContextHolder.getContext().setAuthentication(authResult);
        chain.doFilter(request, response);
    }
}

【问题讨论】:

  • 您第二次调用.authorizeRequests() 会覆盖第一次调用。
  • 如果我正确理解链接的帖子,那与我的问题不一样;在我的情况下,所有 SECURED_URLS (A) 路径都是安全的,但 FREE_URLS (B) 除外,但集合 B 仍然是集合 A 的一部分。
  • 不,你没有正确理解。一个问题是您使用了两次authorizeRequests。这根本没有意义。
  • new AuthenticationFilter(PROTECTED_URLS) 应该只对受保护的 URL 应用过滤器,但 /api/** 包含 /api/token。因此,您的过滤器也适用于免费 URL。您必须排除免费 URL。
  • 您的意思是从受保护的 URL 中排除 URL?所以我必须将受保护的 URL 定义为包含 {"/api/path1/**","/api/path2/**","/api/path3/**"} 而不是 "/api/token" ?

标签: spring spring-boot security spring-security


【解决方案1】:

这可以通过首先放置更具体的配置来解决,以便它首先匹配。

改变你的配置方法如下:

http
    .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
    .exceptionHandling()
        .and()
    .authorizeRequests()
        .requestMatchers(FREE_URLS).permitAll()
        .and()
    .authenticationProvider(provider)
        .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class)
    .authorizeRequests()
        .requestMatchers(FREE_URLS).permitAll()
        .requestMatchers(PROTECTED_URLS).authenticated()
        .and()
    .csrf().disable()
    .formLogin().disable()
    .httpBasic().disable()
    .logout().disable();

【讨论】:

  • 感谢您的回答;我已将您的建议复制到我的代码中,但遗憾的是它没有按预期工作。回复依旧:{ "timestamp": "2020-08-16T14:21:53.388+0000", "status": 401, "error": "Unauthorized", "message": "Unauthorized", "path": "/api/token" }
猜你喜欢
  • 2021-11-30
  • 1970-01-01
  • 2012-07-08
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多