微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决使用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 举报,一经查实,本站将立刻删除。