Spring security DefaultMethodSecurityExpressionHan

2019-07-20 17:15发布

I am attempting to write Spring MVC integration test with Spring Security and Thymeleaf for the view layer.

I have setup my MockMvc object with Spring Security Integration just like all the examples from the documentation.

Integration Test setUp:

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 is configured to utilize the SpringSecurityDialect. (thymeleaf-extras-springsecurity4)

 additionalDialects.add( new SpringSecurityDialect());

For the purpose of being able to utilize spring security expressions in the view layer (example).

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

Now my configuration works perfectly fine outside of testing however, when I try to make an integration test Thymeleaf throws an exception stating that

(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.");

This exception is valid because SecurityExpressionHandler.class is missing from the application context during the integration test.

So my question is... how come a SecurityExpressionHandler.class is registered as spring bean in a regular servlet environment but when using the Integration Test config ctx.getBeansOfType(SecurityExpressionHandler.class) is missing from the context? Is this a bug in Spring Security? Or do I need to add additional logic to register a SecurityExpressionHandler bean for the integration test only?

I tried to "force create" a SecurityExpressionHandler by extending GlobalMethodSecurityConfiguration and @Overriding the createExpressionHandler() and adding it to my test config but still the bean was not registered with the WebApplicationContext.

This is a blocker for me right now because I cannot perform any integration testing on any view file that contains Spring Security expressions embedded inside them.

Spring v4.1.6
Spring Security 4.0.1
Thymeleaf v2.1.4

1条回答
Luminary・发光体
2楼-- · 2019-07-20 17:45

If you are loading the WebApplicationContext for your test using @ContextHierarchy, then this will not work with Spring Framework 4.1.4 through 4.1.6 due to a confirmed bug that will be fixed in 4.1.7.

See SPR-13075 for details.

查看更多
登录 后发表回答