当Spring不可自动操作时,从Spring Security中选择性地将单个过滤器应用于MockMvc

Whi*_*cal 0 java spring spring-security spring-test spring-boot

我的WebSecurityConfigurerAdapter定义为 http.csrf().csrfTokenRepository(csrfTokenRepository());

我想做一个只激活CSRF过滤的集成测试,但是我遇到了一个问题:

  • CSRFTokenRepository未在上下文中公开
  • CSRFilter似乎没有像Spring那样在上下文中暴露出来

我想以下列方式测试:

   this.mockMvc = webAppContextSetup(super.webApplicationContext)
            .apply(springSecurity(CSRFFilter.class)) //This is just a showcase of that I pretend
            .alwaysDo(print())
            .build();
Run Code Online (Sandbox Code Playgroud)

如何有选择地将单个过滤器(如CSRFFilter)应用于我的集成测试而不是通用的SecurityMockMvcConfigurers.springSecurity()?

Fil*_*are 5

请注意,这个答案附有完整的工作样本.

这类问题很有意思.因为它如下

  1. 确定存在问题,该问题未在Stack Overflow问题中公开
  2. 提出了解决该问题的方法
  3. 建议的解决方案成为问题,但我们不知道它是最好的解决方案

因此,我不确定您是否应该在测试中修改应用程序中的过滤器链.最终结果是您没有测试您的应用程序,但是您正在测试永远不会投入生产的已修改应用程序.

为了怀疑,尽管提出的问题是最佳解决方案,但这是可能的.我就是这样做的

我创建了一个自定义过滤器,在执行任何其他过滤器之前返回500错误.

static class FiveHundredFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        response.setStatus(500);
        response.getWriter().write("TEST FILTER CHAIN");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个BeanPostProcessor将此过滤器添加到我的所有过滤器链.您可以选择将其添加到此处的链.

static class SecurityFilterChainPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("springSecurityFilterChain".equals(beanName)) {
            FilterChainProxy fcp = (FilterChainProxy) bean;
            for (SecurityFilterChain fc : fcp.getFilterChains()) {
                fc.getFilters().add(0, new FiveHundredFilter());
            }
        }
        return bean;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我SecurityFilterChainPostProcessor在我的应用程序上下文中公开了bean

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(basePackages = "org/springframework/security/community/samples")
public static class SpringBootApplicationTestConfig {
    @Bean
    SecurityFilterChainPostProcessor securityFilterChainPostProcessor() {
        return new SecurityFilterChainPostProcessor();
    }
}
Run Code Online (Sandbox Code Playgroud)

我相信这应该可以解决你的困境.