简单地测试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 (即HttpSessionSecurityContext )找到的值。

更新

请记住,方法名称中包含角色的任何内容都会自动将“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()); 

它现在有效。