环境 :我有一个基于Spring Boot的微服务架构应用程序,该应用程序由多个基础结构服务和资源服务(包含业务逻辑)组成。授权和身份验证由oAuth2-Service处理,该服务管理用户实体并为客户端创建JWT令牌。
为了完整地测试单个微服务应用程序,我尝试使用 testNG , spring.boot.test , org.springframework.security.test 来构建测试。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, properties = {"spring.cloud.discovery.enabled=false", "spring.cloud.config.enabled=false", "spring.profiles.active=test"}) @AutoConfigureMockMvc @Test public class ArtistControllerTest extends AbstractTestNGSpringContextTests { @Autowired private MockMvc mvc; @BeforeClass @Transactional public void setUp() { // nothing to do } @AfterClass @Transactional public void tearDown() { // nothing to do here } @Test @WithMockUser(authorities = {"READ", "WRITE"}) public void getAllTest() throws Exception { // EXPECT HTTP STATUS 200 // BUT GET 401 this.mvc.perform(get("/") .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) } }
安全性(资源服务器)配置如下
@Configuration @EnableResourceServer public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { // get the configured token store @Autowired TokenStore tokenStore; // get the configured token converter @Autowired JwtAccessTokenConverter tokenConverter; /** * !!! configuration of springs http security !!! */ @Override public void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/**").authenticated(); } /** * configuration of springs resource server security */ @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { // set the configured tokenStore to this resourceServer resources.resourceId("artist").tokenStore(tokenStore); } }
以及在控制器类中注释的以下基于方法的安全检查
@PreAuthorize("hasAuthority('READ')") @RequestMapping(value = "/", method = RequestMethod.GET) public List<Foo> getAll(Principal user) { List<Foo> foos = fooRepository.findAll(); return foos; }
我以为可以,但是在运行测试时,我只会得到一个断言错误
java.lang.AssertionError: Status Expected :200 Actual :401
问题 :我做错了什么吗?还是@WithMockUser不能在oAuth2环境中与@SpringBootTest和@AutoConfigureMockMvc一起使用?如果是这样的话…作为这种(集成)测试的一部分,测试基于路由和方法的安全配置的最佳方法是什么?
附录 :我也尝试了类似以下内容的不同方法…但是它导致了相同的结果:(
this.mvc.perform(get("/") .with(user("admin").roles("READ","WRITE").authorities(() -> "READ", () -> "WRITE")) .accept(MediaType.APPLICATION_JSON))
请参阅 : spring安全性测试 spring boot 1.4测试
@WithMockUser在 SecurityContext中 创建身份验证。同样适用于with(user("username"))。
@WithMockUser
with(user("username"))
默认情况下, OAuth2AuthenticationProcessingFilter 不使用SecurityContext,而是始终根据令牌(“无状态”)构建身份验证。
您可以通过将资源服务器安全性配置中的无状态标志设置为false来轻松更改此行为:
@Configuration @EnableResourceServer public class ResourceServerConfiguration implements ResourceServerConfigurer { @Override public void configure(ResourceServerSecurityConfigurer security) throws Exception { security.stateless(false); } @Override public void configure(HttpSecurity http) {} }
另一个选择是扩展ResourceServerConfigurerAdapter,但是问题在于它带有强制所有请求都经过身份验证的配置。实施接口后,除了无状态之外,您的主要安全配置均保持不变。
当然,仅在测试上下文中将标志设置为 false 。