使用StandaloneSetup的MockMvc进行单元测试时如何启用GlobalMethodsSecurity

时间:2019-04-18 07:39:36

标签: spring-security mockito junit4 mockmvc

使用MockMvc进行单元测试时,将忽略SpringSecurity的@PreAuthorize和@PostAuthorize。但是在正常启动应用程序的同时通过Postman的浏览器访问就可以了

我正在使用Spring 4.3和Spring Security 4.2,而不是Spring Boot。我正在使用MockMvcBuilders.standaloneSetup仅测试控制器。并且不想使用webAppContextSetup来涉及整个应用程序进行测试。

检查了Spring Security的源代码后,我发现Pre和PostAuthorize正在由org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice和org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice检查。但是org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource不包含该控制器。

我认为这是由控制器未由Spring初始化引起的,因此我尝试将其注册到BeanFactory,但它也会失败。

测试代码:

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);

    mockMvc = standaloneSetup(controllers)
                .setValidator(validator)
                .apply(springSecurity(filterChainProxy))
                .alwaysDo(print())
                .build();
}

public void itWillFailWhenUpdateOtherOrg() {
    CurrentUser user = new CurrentUser();
    user.setOrgId(1);
    user.setUsername("testuser");
    mockMvc.perform(put("/orgs/-1")
                .contentType(APPLICATION_JSON)
                .content("{\"name\":\"RootOrg\",\"parent\":100}")
                .with(user(user))).andExpect(status().isForbidden());
    verify(orgService, never()).update(any());
}

控制器代码:

@PutMapping("/org/{id}")
@PreAuthorize("principal.orgId == #orgDO.parent")
public OrgDO update(@PathVariable Integer id, @RequestBody OrgDO orgDO) {
}

测试时,状态码为200,而不是403。

java.lang.AssertionError: Status 
Expected :403
Actual   :200

由于principal.orgId != #orgDO.parent,我预计放置请求将失败并返回状态代码403。

请确保不要将所有类都包含到Spring上下文中,我只想测试控制器类。

非常感谢您。

1 个答案:

答案 0 :(得分:0)

经过几个小时的挖掘,这是为什么: MockMvcBuilders.standaloneSetup通常会通过手动实例化的控制器传递(不使用Spring并因此不使用AOP)。因此,不会拦截PreAuthorize,并且跳过安全检查。因此,您可以使用@Autowire控制器并将其传递给MockMvcBuilders.standaloneSetup(这可能有点违背使用独立安装程序的目的,因为它会创建其余的控制器...),也可以直接使用WebApplicationContext:MockMvcBuilders.webAppContextSetup与自动连接WepAppContext。

相关问题