簡體   English   中英

Testing Spring rest controller with Spring Security OAuth

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM