【问题标题】:Spring security: Cannot permit access to resource when adding custom filterSpring security:添加自定义过滤器时不允许访问资源
【发布时间】:2019-02-10 11:26:54
【问题描述】:

我的 Spring Security 有以下配置

http
    // if I gonna comment adding filter it's gonna work as expected
    .addFilterBefore(tokenAuthenticationFilter, BasicAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/rest/_health")
            .permitAll()

            .anyRequest()
            .authenticated()

            .and()
            .csrf()
            .disable();

因此,如果没有自定义过滤器,一切都会按预期工作 - 我可以访问 /rest/_health 并拒绝访问其他所有内容。

但是当我添加此过滤器时 - 匹配器不起作用,过滤器即使对“permitAll”资源也有效。

我的过滤器中的代码如下所示:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    try {
        String token = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);

        Authentication authentication = authenticationManager.authenticate(
                new TokenBasedAuthentication(token)
        );

        SecurityContextHolder.getContext().setAuthentication(authentication);

        chain.doFilter(request, response);
    } catch (AuthenticationException ex) {
        authenticationEntryPoint.commence(httpRequest, httpResponse, ex);
    }
}

有什么建议吗?

【问题讨论】:

    标签: java spring-security servlet-filters


    【解决方案1】:

    过滤器在端点检查之前执行。在您的情况下,不成功的身份验证会中止过滤器链并让接入点处理其余部分。有了这个,您根本不允许匿名访问。您需要将 Authentication 设置为 null 以指示匿名用户正在访问端点。

    尝试以下方法:

        Authentication authentication = null;
        String token = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);
        //check if not anonymous and preceed with authentication
        if (token != null && !token.isEmpty()) {
            try {
    
                authentication = authenticationManager.authenticate(
                    new TokenBasedAuthentication(token));
    
            } catch (AuthenticationException ex) {
                //illigal access atempt
                authenticationEntryPoint.commence(httpRequest, httpResponse, ex);
            }
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    

    【讨论】:

      【解决方案2】:

      在我的配置(扩展 WebSecurityConfigurerAdapter)中,我是这样做的:

              http.csrf().disable().
                  addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                  .authorizeRequests()
                  .antMatchers("/login*", "/logout*").permitAll().anyRequest()
                  .authenticated()
              .and()
                  .formLogin()
                      .loginPage("/login")
                      .defaultSuccessUrl("/secured/index")
                      .failureUrl("/login?error=true").permitAll()
              .and()
                  .logout()
                      .invalidateHttpSession(true)
                      .clearAuthentication(true)
                      .deleteCookies("JSESSIONID")
                      .logoutUrl("/logout")
                      .logoutSuccessUrl("/login")
                      .permitAll();
      
      @Override
      public void configure(WebSecurity web) throws Exception {
          web.ignoring().antMatchers("/static/**", "/webjars/**", "/error*");
      }
      

      也许并不完美,但它确实有效。

      【讨论】:

      • 对我来说没有按预期工作,实际上,兄弟,我的配置几乎相同,除了登录和注销
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      • 2014-10-11
      • 2012-10-27
      • 1970-01-01
      • 2011-08-23
      • 2014-07-28
      • 2011-07-23
      相关资源
      最近更新 更多