如何解决使用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)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。