使用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上下文中,我只想测试控制器类。
非常感谢您。
答案 0 :(得分:0)
经过几个小时的挖掘,这是为什么:
MockMvcBuilders.standaloneSetup
通常会通过手动实例化的控制器传递(不使用Spring并因此不使用AOP)。因此,不会拦截PreAuthorize,并且跳过安全检查。因此,您可以使用@Autowire控制器并将其传递给MockMvcBuilders.standaloneSetup(这可能有点违背使用独立安装程序的目的,因为它会创建其余的控制器...),也可以直接使用WebApplicationContext:MockMvcBuilders.webAppContextSetup与自动连接WepAppContext。