自定义身份验证使用Java Config在多个HttpSecurity对象中进行过滤

时间:2016-05-18 15:36:17

标签: java spring spring-mvc spring-security

我希望有两个不同的http网页配置,其中包含使用spring boot和spring java config的自定义身份验证过滤器。 我按照可在此处找到的示例应用程序:https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi-http-web-configuration。 我的理解是,这将最终出现在每个Web配置的单独的弹簧过滤器链中。但是,尽管Web配置URL模式与请求不匹配,但都会调用这两个过滤器。 例如,请求http://localhost:8080/api/dosomething将调用两个过滤器,而不仅仅是CustomApiAuthenticationFilter。当然,有可能在doFilterInternal中检查请求url并忽略请求,如果它不匹配但我认为这应该通过尊重相应Web配置的url模式自动完成。 此外,我的RestController不会被分别调用Postman只接收状态代码200 OK而没有响应主体。

两个问题: 1.这种行为是设计还是配置错误? 2.为什么我的RestController没有被调用?

@EnableWebSecurity
public class SecurityConfiguration {

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

        @Bean
        public GenericFilterBean apiAuthenticationFilter() {
            return new CustomApiAuthenticationFilter();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.antMatcher("/api/**").addFilterAfter(apiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests().antMatchers("/api/**").authenticated();
        }
    }

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

        @Bean
        public GenericFilterBean webAuthenticationFilter() {
            return new CustomWebAuthenticationFilter();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/").addFilterAfter(webAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authorizeRequests().antMatchers("/").authenticated();
        }
    }
}

public class CustomApiAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("API")));
        SecurityContextHolder.getContext().setAuthentication(auth);
    }
}

public class CustomWebAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("USER")));
        SecurityContextHolder.getContext().setAuthentication(auth);
    }
}

@RestController
public class ApiController {
    @RequestMapping(value = "/api/v1/dosomething", method = RequestMethod.GET)
    public String getSomething() {
        return "something";
    }
}

2 个答案:

答案 0 :(得分:1)

感谢M. Deinum,他给了我正确的答案。以下现在按预期工作,但我仍然不确定这是否合法。

@EnableWebSecurity
public class SecurityConfiguration {

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

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.antMatcher("/api/**")
                .addFilterAfter(new CustomApiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests().anyRequest().hasRole("API");
        }
    }

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

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/")
                .addFilterAfter(new CustomWebAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authorizeRequests().anyRequest().hasRole("USER");
        }
    }
}

public class CustomApiAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_API")));
        SecurityContextHolder.getContext().setAuthentication(auth);
        filterChain.doFilter(request, response);
    }
}

public class CustomWebAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Authentication auth = new UsernamePasswordAuthenticationToken("sub", "password", ImmutableList.of(new SimpleGrantedAuthority("ROLE_USER")));
        SecurityContextHolder.getContext().setAuthentication(auth);
        filterChain.doFilter(request, response);
    }
}

答案 1 :(得分:0)

除了我之前的回答,还可以通过手动创建相应的弹簧@Bean并禁用自动过滤器注册来保留FilterRegistrationBean注释。这也将保留过滤器中的自动装配。

public class SecurityConfiguration {

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

        @Bean
        public FilterRegistrationBean customApiAuthenticationFilterRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean(customApiAuthenticationFilter());
            registration.setEnabled(false);
            return registration;
        }

        @Bean
        public GenericFilterBean customApiAuthenticationFilter() {
            return new CustomApiAuthenticationFilter();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/api/**").addFilterAfter(customApiAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authorizeRequests().anyRequest().hasRole("API").and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        }
    }

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

        @Bean
        public FilterRegistrationBean customWebAuthenticationFilterRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean(customWebAuthenticationFilter());
            registration.setEnabled(false);
            return registration;
        }

        @Bean
        public GenericFilterBean customWebAuthenticationFilter() {
            return new CustomWebAuthenticationFilter();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/").addFilterAfter(customWebAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class)
                .authorizeRequests().antMatchers("/").hasRole("USER");
        }
    }
}