[英]Testing Spring rest controller with Spring Security OAuth
我正在嘗試使用 Spring 引導 @WebMvcTest 測試我的 controller。 我還實現了 SPring OAuth 安全性(資源和授權服務器),因此要到達端點,您需要獲得授權。
出於這個原因,我不能像這樣測試我的 controller:
@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);
}
}
然后在 controller 測試中禁用安全性,您需要執行下一步
@WebMvcTest(MyController.class)
@AutoConfigureMockMvc(addFilters = false)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.