为什么这个spring安全配置会阻塞所有路径?

时间:2015-10-26 01:19:49

标签: spring spring-security spring-boot

public class AuthenticationFilter extends GenericFilterBean {

SecureService secureService;

public AuthenticationFilter(SecureService secureService) {
    this.secureService=secureService;
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
    Authentication authentication=secureService.getAuthentication(httpServletRequest);
    if(authentication!=null) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
        filterChain.doFilter(servletRequest, servletResponse);
        SecurityContextHolder.getContext().setAuthentication(null);
    }
}

}


@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
SecureService secureService;
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.addFilterBefore(new AuthenticationFilter(secureService), BasicAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers(HttpMethod.GET, "/businesses/**").permitAll()
            .antMatchers(HttpMethod.GET, "/users/login").permitAll()
            .antMatchers(HttpMethod.POST, "/users/").permitAll()
            .antMatchers(HttpMethod.GET, "/reviews/").permitAll()
            .antMatchers(HttpMethod.GET, "/reviews/search").permitAll()
            .antMatchers(HttpMethod.GET, "/reviews/**").permitAll()
            .antMatchers("/").permitAll().and()
            .authorizeRequests().anyRequest().authenticated();
}
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManagerBean();
    }
}

这种配置有什么问题?我跟着这个link写了url身份验证。但是我的应用程序会阻止所有请求,忽略代码中指定的所有匹配器。我用谷歌搜索,有人说规则的顺序很重要。但即使我更改了订单,AuthenticationFilter 也会一直被调用并阻止所有请求

1 个答案:

答案 0 :(得分:0)

问题是您中断了过滤器链。如下所示,它应该工作。

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        Authentication authentication = secureService.getAuthentication(httpServletRequest);
        if (authentication != null) {
            SecurityContextHolder.getContext().setAuthentication(authentication);

        }

        filterChain.doFilter(servletRequest, servletResponse);
        SecurityContextHolder.getContext().setAuthentication(null);
    }

另一件事是,如果HttpServlerRequest不包含身份验证,则会在SecureService中抛出UserNotFoundException。 在AuthenticationFilter中你似乎期望在这种情况下为null?因此,如果不存在身份验证,则在SecureService中返回null:

public Authentication getAuthentication(HttpServletRequest httpServletRequest) {
    final String token=httpServletRequest.getHeader(Headers.AUTH_HEADER_NAME);
    if(token!=null){
        final User user=parseToken(token);
        if(user!=null){
            return new UserAuthentication(user);
        }
    }
    return null;
}

如果要保留UserNotFoundException,则只将doFilterMethod更改为以下内容:

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

    try {
        Authentication authentication = secureService.getAuthentication(httpServletRequest);
        if (authentication != null) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    }catch(UserNotFoundException e){
    }finally {
        filterChain.doFilter(servletRequest, servletResponse);
        SecurityContextHolder.getContext().setAuthentication(null);
    }

}