运行Spring Boot集成测试的最佳方法是再次配置OAuth Resource服务器的Web应用程序。
我可以想到两种理论方法:
我想知道其他人如何解决这个问题。
我使用Spring Security 4.x @WithSecurityContext('user')注释创建SecurityContext具有'user'登录状态的模拟。然后,在使用调用我的REST API时,MockMvc我检索SecurityContext并将其附加到调用中。
@WithSecurityContext('user')
SecurityContext
'user'
MockMvc
像这样:
@Test @Transactional @WithSecurityContext('user') public void getAllParcels() throws Exception { // Initialize the database long size = parcelRepository.count(); parcelRepository.saveAndFlush(parcel); // Get all the parcels restParcelMockMvc.perform(get("/api/parcels").with(security())) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.[" + size + "].id").value(parcel.getId())) .andExpect(jsonPath("$.[" + size + "].lot").value(DEFAULT_LOT)) .andExpect(jsonPath("$.[" + size + "].localName").value(DEFAULT_LOCAL_NAME)); }
security()静态方法在哪里:
security()
public static RequestPostProcessor security() { return SecurityMockMvcRequestPostProcessors.securityContext(SecurityContextHolder.getContext()); }
因此,为我的测试方法创建了具有登录身份验证用户的@WithSecurityContext('user')模拟对象。然后在该方法中,我检索此模拟并将其附加到REST API调用,以使我的oAuth认为用户已通过身份验证。基本上,这是您在问题中建议的第一种方法。SecurityContext``'user'``SecurityContext
SecurityContext``'user'``SecurityContext
为此,您必须将OAuth切换为全状态以进行测试。否则它将无法正常工作。
即像这样:
@Configuration public class OAuth2ServerConfiguration { @Configuration @EnableResourceServer protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Autowired(required = false) @Qualifier("oauth2StatelessSecurityContext") private Boolean stateless = Boolean.TRUE; // STATEFUL switching for tests! @Inject private Http401UnauthorizedEntryPoint authenticationEntryPoint; @Inject private AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler; @Override public void configure(HttpSecurity http) throws Exception { http .exceptionHandling() .authenticationEntryPoint(authenticationEntryPoint) .and() .logout() .logoutUrl("/api/logout") .logoutSuccessHandler(ajaxLogoutSuccessHandler) .and() .csrf() .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")) .disable() .headers() .frameOptions().disable().and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers("/api/authenticate").permitAll() .antMatchers("/api/register").permitAll() .antMatchers("/api/logs/**").hasAnyAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/api/**").authenticated() .antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN) .antMatchers("/protected/**").authenticated(); } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.stateless(stateless); super.configure(resources); } } ...
您会看到stateless仅在测试中注入的我的属性。在正常运行中,它使用默认值true(因此它是无状态的)。对于测试,我oauth2StatelessSecurityContext用值声明Bean,false因此它对于测试变为有状态。
stateless
true
oauth2StatelessSecurityContext
false
我为测试定义此配置:
@Configuration public class OAuth2Statefull { @Bean @Primary public Boolean oauth2StatelessSecurityContext() { return Boolean.FALSE; } }
那就是我做到的。我希望我的解释是可以理解的。