Spring security DefaultMethodSecurityExpressionHandler bean 未注册 Integration Test 的默认 spring security

Posted

技术标签:

【中文标题】Spring security DefaultMethodSecurityExpressionHandler bean 未注册 Integration Test 的默认 spring security 配置【英文标题】:Spring security DefaultMethodSecurityExpressionHandler bean is not registered for Integration Test's default spring security config 【发布时间】:2015-08-17 06:04:23 【问题描述】:

我正在尝试使用 Spring Security 和 Thymeleaf 为视图层编写 Spring MVC 集成测试。

我已经使用 Spring Security Integration 设置了我的 MockMvc 对象,就像文档中的所有示例一样。

集成测试设置:

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;

    @Autowired 
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before
    public void setup() 

        mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                //.defaultRequest(get("/").with(user(someUser)))
                .apply(springSecurity())
                .build();
    

Thymeleaf 被配置为使用 SpringSecurityDialect。 (thymeleaf-extras-springsecurity4)

 additionalDialects.add( new SpringSecurityDialect());

为了能够在视图层中使用 spring 安全表达式(示例)。

<p sec:authorize="hasRole('ROLE_USER')"> User logged in</p>

现在我的配置在测试之外工作得非常好,但是,当我尝试进行集成测试时,Thymeleaf 会抛出一个异常,指出

(org.thymeleaf.extras.springsecurity4.auth.AuthUtils.class)

@SuppressWarnings("unchecked")
private static SecurityExpressionHandler<FilterInvocation> getExpressionHandler(final ServletContext servletContext) 

    final ApplicationContext ctx =
            WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);

    final Map<String, SecurityExpressionHandler> expressionHandlers =
            ctx.getBeansOfType(SecurityExpressionHandler.class);

    for (SecurityExpressionHandler handler : expressionHandlers.values()) 
        if (FilterInvocation.class.equals(GenericTypeResolver.resolveTypeArgument(handler.getClass(), SecurityExpressionHandler.class))) 
            return handler;
        
    

    throw new TemplateProcessingException(
            "No visible SecurityExpressionHandler instance could be found in the application " +
            "context. There must be at least one in order to support expressions in Spring Security " +
            "authorization queries.");

此异常有效,因为在集成测试期间应用程序上下文中缺少 SecurityExpressionHandler.class。

所以我的问题是...为什么 SecurityExpressionHandler.class 在常规 servlet 环境中注册为 spring bean,但是在使用集成测试配置时缺少 ctx.getBeansOfType(SecurityExpressionHandler.class)从上下文?这是 Spring Security 中的错误吗?或者我是否需要添加额外的逻辑来为集成测试注册一个 SecurityExpressionHandler bean?

我尝试通过扩展 GlobalMethodSecurityConfiguration 和 @Overriding createExpressionHandler() 并将其添加到我的测试配置中来“强制创建”SecurityExpressionHandler,但该 bean 仍未向 WebApplicationContext 注册。

这对我来说现在是一个障碍,因为我无法对包含嵌入其中的 Spring Security 表达式的任何视图文件执行任何集成测试。

Spring v4.1.6
Spring Security 4.0.1
Thymeleaf v2.1.4

【问题讨论】:

降级到 Spring v4.1.3 “修复”了这个问题......这让我怀疑这是一个错误。 【参考方案1】:

如果您使用 @ContextHierarchy 为您的测试加载 WebApplicationContext,那么这将不适用于 Spring Framework 4.1.4 到 4.1.6,因为已确认的错误将在 4.1.7 中修复。

详情请见SPR-13075。

【讨论】:

以上是关于Spring security DefaultMethodSecurityExpressionHandler bean 未注册 Integration Test 的默认 spring security的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security:2.4 Getting Spring Security

没有 JSP 的 Spring Security /j_spring_security_check

Spring-Security

Spring Security 登录错误:HTTP 状态 404 - /j_spring_security_check

未调用 Spring Security j_spring_security_check

Spring Security入门(3-7)Spring Security处理页面的ajax请求