Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Java配置在多个HttpSecurity对象中自定义身份验证过滤器_Java_Spring_Spring Mvc_Spring Security - Fatal编程技术网

使用Java配置在多个HttpSecurity对象中自定义身份验证过滤器

使用Java配置在多个HttpSecurity对象中自定义身份验证过滤器,java,spring,spring-mvc,spring-security,Java,Spring,Spring Mvc,Spring Security,我想使用SpringBoot和SpringJavaConfig使用两种不同的http web配置和自定义身份验证过滤器。 我遵循了可以在此处找到的示例应用程序:。 我的理解是,对于每种web配置,这都会在一个单独的spring过滤器链中结束。尽管web配置url模式与请求不匹配,但这两个过滤器都会被调用。 例如,请求将调用这两个过滤器,而不仅仅是CustomApiAuthenticationFilter。当然,可以在doFilterInternal中检查请求url,如果不匹配则忽略请求,但我认为

我想使用SpringBoot和SpringJavaConfig使用两种不同的http web配置和自定义身份验证过滤器。 我遵循了可以在此处找到的示例应用程序:。 我的理解是,对于每种web配置,这都会在一个单独的spring过滤器链中结束。尽管web配置url模式与请求不匹配,但这两个过滤器都会被调用。 例如,请求将调用这两个过滤器,而不仅仅是CustomApiAuthenticationFilter。当然,可以在doFilterInternal中检查请求url,如果不匹配则忽略请求,但我认为这应该通过尊重相应web配置的url模式自动完成。 此外,我的RestController没有被调用,邮递员只收到状态代码200OK,没有响应主体

两个问题: 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";
    }
}

感谢迪纳姆先生给了我正确的答案。下面的方法现在可以按预期工作,但我仍然不确定这是否是一种合法的方法

@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);
    }
}

除了我前面的答案之外,还可以通过手动创建相应的spring
FilterRegistrationBean
并禁用自动过滤器注册来保留
@Bean
注释。这也将保留过滤器中的自动布线

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");
        }
    }
}

您的过滤器是一个bean。Spring Boot检测到这些,并将它们添加到常规过滤器链,而不仅仅是Spring Security过滤器链。因此,它们甚至可能会被调用两次而不是一次。当您扩展
OncePerRequestFilter
时,它们只会被调用一次,但问题是该过滤器被检测为普通的
javax.servlet.filter
,因此也被添加为常规过滤器。因此,executionOK在删除
@Bean
注释后,只调用正确的过滤器。但是我仍然有一个问题,我的
RestController
没有被调用。有什么想法吗?在
doFilterInternal
中,我可以通过
request.getRequestDispatcher(request.getRequestURI()).forward(请求,响应)手动转发请求在成功的身份验证之后,但是这种方法在我看来是错误的,对吗?实际上是你的
doFilterInternal
方法破坏了东西。它在您的过滤器处停止处理。在您的方法中,您必须调用过滤器链以继续处理,否则请求将立即停止。