使用Spring Security OAuth测试Spring rest控制器



我正在尝试使用Spring boot@WebMvcTest测试我的控制器。我还实现了SPring-OAuth安全性(资源和授权服务器(,所以要到达端点,您需要获得授权。

由于这个原因,我不能这样测试我的控制器:

@WebMvcTest(MyController.class)
public class MyControllerTest {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private MyService service;
@Test
public void myTest() throws Exception {
//Arrange request

//Act
mvc.perform
(MockMvcRequestBuilders
.post("/v1/my-controller/type", type.name())
.characterEncoding(StandardCharsets.UTF_8.name())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(requestDTO)))
//Assert
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().json(objectMapper.writeValueAsString("")));
}

因为它需要资源服务器。但问题是,当我运行这个测试时,我得到了下一个错误:

***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.danfoss.cloud.prosa.restapi.security.WebSecurityConfig$OAuthResourceServer required a bean of type 'org.springframework.security.oauth2.provider.token.TokenStore' that could not be found.

Action:
Consider defining a bean of type 'org.springframework.security.oauth2.provider.token.TokenStore' in your configuration.

我的资源服务器看起来像

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Configuration
@EnableResourceServer
public static class OAuthResourceServer extends ResourceServerConfigurerAdapter {

private final TokenStore tokenStore;
////CANNOT INJECT DURING WEB CONTEXT START
@Autowired
public OAuthResourceServer(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId("resource")
.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/status")
.permitAll()
.anyRequest()
.access("isAuthenticated()");
}
private String createAuthorizationExpression(String ipWhitelist) {
return null;
}
}
}

重要的一点是,应用程序运行良好,并且在运行过程中可以很好地注入TokenStore。

如何克服这个问题?

通过如下解耦配置解决了此问题:

@Configuration
public class Config {
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(mainDataSource());
}
....
other beans
}
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
@Configuration
@EnableWebSecurity
@EnableResourceServer
public class OAuthResourceServer extends ResourceServerConfigurerAdapter {
private final TokenStore tokenStore;

@Autowired
public OAuthResourceServer(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId("resource")
.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/status",
"/")
.permitAll()
.anyRequest()
.access(
...
);
}

}
@Configuration
@EnableAuthorizationServer
public class OAuthAuthorizationServer extends AuthorizationServerConfigurerAdapter {
...
private final AuthenticationManager authenticationManager;
...
private final TokenStore tokenStore;
...

@Autowired
public OAuthAuthorizationServer(
....
AuthenticationManager authenticationManager,
TokenStore tokenStore,
...
) {
this.restUserDetailsService = restUserDetailsService;
this.oAuthRestAuthenticationProvider = oAuthRestAuthenticationProvider;
this.authenticationManager = authenticationManager;
this.jdbcClientDetailsService = jdbcClientDetailsService;
this.tokenStore = tokenStore;
this.authorizationCodeServices = authorizationCodeServices;
}
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
tokenServices.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds);
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(true);
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(jdbcClientDetailsService);
tokenServices.setSupportRefreshToken(true);
tokenServices.setAuthenticationManager(authenticationManager);
return tokenServices;
}
@Autowired
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(oAuthRestAuthenticationProvider);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(jdbcClientDetailsService);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.approvalStoreDisabled()
.authorizationCodeServices(authorizationCodeServices)
.tokenStore(tokenStore)
.tokenServices(tokenServices())
.authenticationManager(authenticationManager)
.userDetailsService(restUserDetailsService);
}
}

然后要禁用控制器测试中的安全性,您需要进行下一次

@WebMvcTest(MyController.class)
@AutoConfigureMockMvc(addFilters = false)

最新更新