根据请求匹配应用不同的身份验证过滤器

时间:2018-10-10 19:32:40

标签: java spring-boot spring-security x509 websecurity

在Spring Boot 2.0.3应用程序中,我想根据请求路径应用多种身份验证方法。

预期行为

用于匹配的请求;

  • /静态/ **
    • 不应用任何身份验证过滤器,允许所有
  • /安全/ **
    • 期待并验证客户端证书
  • / api / **
    • 通过HTTP Basic或HTTP摘要进行身份验证

观察到的行为

无论我请求的URL是什么,所有身份验证过滤器始终按以下顺序应用;

  1. X509AuthenticationFilter
  2. BasicAuthenticationFilter
  3. CustomDigestAuthenticationFilter

过滤器可以正常工作,并且使用任何一种方法进行身份验证都没有问题。但是在某些情况下,应用整个FilterChain会导致问题,例如,如果Web浏览器已缓存了Authorization标头,则Web浏览器将不要求提供客户端证书。

主要问题是; 如何将不同的过滤器隔离到其特定的请求域?

更新/编辑

来自http://support.sas.com/documentation/cdl/en/sqlproc/63043/HTML/default/viewer.htm#n1tupenuhmu1j0n19d3curl9igt4.htmSpring Security multiple url ruleset not working together 的输入。不幸的是,这种方法的行为仍然存在。

WebSecurityConfig类

@EnableWebSecurity
public class WebSecurityConfig {

    private final CertificateAuthenticationProvider certificateAuthenticationProvider;
    private final CustomBasicAuthenticationProvider customBasicAuthenticationProvider;

    @Autowired
    public WebSecurityConfig(CertificateAuthenticationProvider certificateAuthenticationProvider, CustomBasicAuthenticationProvider customBasicAuthenticationProvider) {
        this.certificateAuthenticationProvider = certificateAuthenticationProvider;
        this.customBasicAuthenticationProvider = customBasicAuthenticationProvider;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(certificateAuthenticationProvider);
        auth.authenticationProvider(customBasicAuthenticationProvider);
    }

    @Configuration
    @Order(1)
    public static class SecureTestbedWebConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http    .antMatcher("/secure/**").authorizeRequests().anyRequest().authenticated()
                    .and().x509().x509AuthenticationFilter(x509AuthenticationFilter())
                    .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
        }

        @Bean
        public CustomX509AuthenticationFilter x509AuthenticationFilter() {
            CustomX509AuthenticationFilter customX509AuthenticationFilter = new CustomX509AuthenticationFilter();
            customX509AuthenticationFilter.setAuthenticationManager(authenticationManager());
            return customX509AuthenticationFilter;
        }

        @Bean
        @Override
        protected AuthenticationManager authenticationManager() {
            try {
                return super.authenticationManager();
            } catch (Exception ex) {
                throw new IllegalStateException("Failed to extract AuthenticationManager.", ex);
            }
        }
    }

    @Configuration
    @Order(2)
    public static class ApiAuthenticationConfigurationAdapter extends WebSecurityConfigurerAdapter {

        private final CustomBasicAuthenticationEntryPoint customBasicAuthenticationEntryPoint;
        private final AccessDao accessDao;

        @Autowired
        public ApiAuthenticationConfigurationAdapter(CustomBasicAuthenticationEntryPoint customBasicAuthenticationEntryPoint, AccessDao accessDao) {
            this.customBasicAuthenticationEntryPoint = customBasicAuthenticationEntryPoint;
            this.accessDao = accessDao;
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http    .antMatcher("/api/**")
                    .requestMatcher(new BasicRequestMatcher())
                    .authorizeRequests().anyRequest().authenticated()
                    .and().httpBasic().authenticationEntryPoint(customBasicAuthenticationEntryPoint)
                    .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
                    .and().addFilterAfter(customDigestAuthenticationFilter(), BasicAuthenticationFilter.class);
        }

        @Bean
        public CustomDigestAuthenticationFilter customDigestAuthenticationFilter() {
            return new CustomDigestAuthenticationFilter(accessDao);
        }
    }

    @Configuration
    @Order(3)
    public static class NoAuthenticationNeededConfigurationAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http    .antMatcher("/static/**").authorizeRequests()
                    .antMatchers(HttpMethod.GET).permitAll();
        }
    }

    private static class BasicRequestMatcher implements RequestMatcher {
        @Override
        public boolean matches(HttpServletRequest request) {
            String auth = request.getHeader("Authorization");
            boolean isMatching = auth != null && (auth.startsWith("Basic") || auth.startsWith("Digest"));
            log.debug("HTTP {} {}, isMatching; {}", request.getMethod(), request.getRequestURI(), isMatching);
            return isMatching;
        }
    }
}

0 个答案:

没有答案