简单地测试Spring Boot Security
我正在努力测试受Spring Security保护的URL的访问控制。
配置如下所示:
http .authorizeRequests() .antMatchers("/api/user/**", "/user").authenticated() .antMatchers("/api/admin/**", "/templates/admin/**", "/admin/**").hasAuthority("ADMIN") .anyRequest().permitAll();
测试类看起来像这样:
package com.kubukoz.myapp; import com.kubukoz.myapp.config.WebSecurityConfig; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.security.web.FilterChainProxy; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import javax.transaction.Transactional; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = {MyApplication.class, WebSecurityConfig.class}) @WebAppConfiguration @TransactionConfiguration(defaultRollback = true) @Transactional(rollbackOn = Exception.class) public class MyApplicationTests { @Autowired private WebApplicationContext context; private MockMvc mockMvc; @Autowired private FilterChainProxy filterChainProxy; @Before public void setUp() { mockMvc = MockMvcBuilders.webAppContextSetup(context) .dispatchOptions(true) .addFilters(filterChainProxy) .build(); } @Test public void testAnonymous() throws Exception { mockMvc.perform(get("/api/user/account")).andExpect(status().is3xxRedirection()); } @Test public void testUserAccessForAccount() throws Exception{ mockMvc.perform(get("/api/user/account")).andExpect(status().isOk()); } }
最后两个测试通过的最简单方法是什么? @WithMockUser无效。
您不应该直接添加FilterChainProxy。 相反,您应该应用引用所指示的SecurityMockMvcConfigurers.springSecurity()
。 下面是一个例子:
mockMvc = MockMvcBuilders .webAppContextSetup(context) .apply(springSecurity()) .build();
结果是:
-
FilterChainProxy
作为Filter
添加到MockMvc
(就像你做的那样) - 添加了
TestSecurityContextHolderPostProcessor
为什么需要TestSecurityContextHolderPostProcessor
? 原因是我们需要将当前用户从测试方法传递到创建的MockHttpServletRequest
。 这是必要的,因为Spring Security的SecurityContextRepositoryFilter
会将SecurityContextHolder上的任何值覆盖为当前SecurityContextRepository
(即HttpSession
的SecurityContext
)找到的值。
更新
请记住,方法名称中包含角色的任何内容都会自动将“ROLE_”前缀添加到传入的字符串中。
根据您的评论,问题是您需要更新配置以使用hasRole而不是hasAuthority(因为您的注释使用角色):
.authorizeRequests() .antMatchers("/api/user/**", "/user").authenticated() .antMatchers("/api/admin/**", "/templates/admin/**", "/admin/**").hasRole("ADMIN") .anyRequest().permitAll();
另外
您在Spring Security 4.0.2+中可以使用:
@WithMockUser(authorities="ADMIN")
好吧,想通了。
mockMvc.perform(get("/api/user/account") .with(user("user"))) .andExpect(status().isOk());
它现在有效。