当前位置: 首页 > 知识库问答 >
问题:

获取403禁止在Oaut2安全(客户端凭据)资源服务器应用程序中的WebFLuxTest

张英范
2023-03-14

我有一个反应式(springwebflux)web应用程序,在这个应用程序中,我只有很少的restapi是受保护的资源。(Oauth2)。要手动访问它们,我需要获取一个具有客户端凭据授权类型的授权令牌,并在请求中使用该令牌。

现在,我需要编写测试,通过Spring的WebTestClient调用API。我被禁止尝试访问API。在编写测试用例时,我哪里做错了。

以下是我的安全配置:

@EnableWebFluxSecurity
public class WebSecurityConfiguration {

  @Bean
  SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeExchange()
        .pathMatchers(ACTUATOR_ENDPOINT_PATTERN)
        .permitAll()
        .pathMatchers("/my/api/*")
        .hasAuthority("SCOPE_myApi")
        .anyExchange().authenticated()
        .and()
        .oauth2ResourceServer()
        .jwt();
    http.addFilterAfter(new SomeFilter(), SecurityWebFiltersOrder.AUTHORIZATION);

    return http.build();
  }

  @Bean
  public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
      ReactiveClientRegistrationRepository clientRegistrationRepository,
      ReactiveOAuth2AuthorizedClientService authorizedClientService) {

    ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
        ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
            .clientCredentials()
            .build();

    AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
        new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
            clientRegistrationRepository, authorizedClientService);
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    return authorizedClientManager;
  }

  @Bean
  public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
    return WebClient.builder().filter(oauth).build();
  }

}

注意:-我需要这个webClient bean,因为在那个过滤器(我添加到SecurityWebFilterChain)中,我调用了另一个受保护的资源/API,并且该API的响应是在反应性上下文中设置的

我的申请是:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: ${oidc-issuer-uri}
      client:
        provider:
          myProvider:
            issuer-uri: ${oidc-issuer-uri}
        registration:
          myProvider:
            client-id: another-service-client
            client-secret: ${another-service-clientSecret}
            scope: anotherServiceScope
            authorization-grant-type: client_credentials

我的控制器:

@RestController
public class MyController {
 @GetMapping(value = "/my/api/greet")
  public Mono<String> greet() {
return Mono.subscriberContext()
        .flatMap(context -> {
String someVal = context.get("MY_CONTEXT"); //This context is being set inside the filter 'SomeFilter'
//Use this someVal
return Mono.just("Hello World");
});
    
  }
}

我的测试用例:

@RunWith(SpringRunner.class)
@WebFluxTest(controllers = {MyController.class})
@Import({WebSecurityConfiguration.class})
@WithMockUser
public class MyControllerTest {


  @Autowired
  private WebTestClient webTestClient;

  @Test
  public void test_greet() throws Exception {

    webTestClient.mutateWith(csrf()).get()
        .uri("/my/api/greet")
        .exchange()
        .expectStatus().isOk();
  }

}

注意:-我不能通过不使用WebSecurity配置类来绕过。因为正在WebSecurity配置中添加的筛选器中设置被动上下文。

共有1个答案

谯英彦
2023-03-14

这里需要2件事:

  1. 首先要访问/my/api/greet,webTestClient需要SCOPE\u myApi,因为这里不涉及“用户”,所以我们不需要@WithMockUser
  @Test
  public void test_greet() {
    
    webTestClient
        .mutateWith(mockOidcLogin().authorities(new SimpleGrantedAuthority("SCOPE_myApi")))
        .get()
        .uri("/my/api/greet")
        .exchange()
        .expectStatus().isOk()
        .expectBody(String.class).isEqualTo("mockSasToken");
  }

对于这个选项,可以使用spring boot@AutoConfigureWireMock(port=0)自动启动wiremock服务器,并在随机端口关闭。

接下来,我们在测试方法中存根“另一个服务”和Oauth2令牌endpoint的响应。

最后,我们需要一个“测试”spring概要文件和相应的应用程序测试。yaml,我们告诉spring使用wiremockendpoint获取令牌:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: http://localhost:${wiremock.server.port}/.well-known/jwks_uri
      client:
        provider:
          myProvider:
            token-uri: http://localhost:${wiremock.server.port}/.well-known/token
        registration:
          myProvider:
            client-id: mockClient
            client-secret: mockSecret
 类似资料:
  • 我正在开发一个服务器端应用程序,用于从我们的Office 365中检索电子邮件,过滤电子邮件并将其存储在我们的数据库中,而无需用户登录。如果您想查看一些详细信息,请参阅我之前问题的链接。 我有以下方法 如果我尝试使用https://graph.microsoft.com/v1.0/users/在rest Temboard我将得到一个用户列表,但对于一个特定的用户,上面的代码返回403。 您能否建议

  • 我正在尝试使用Spring security保护我的网站,但我一直收到

  • 我一直在开发环境中实现AWS S3与C#AWS SDK的集成,一切都进展顺利。部分要求是IAM AccessKey和秘书密钥旋转,凭据/配置文件存储或缓存,并且在这个过程中还需要承担一个角色。 我有一个方法,在使用AccessKey、SecretKey和RegionEndpoint初始化后返回凭据,使用RoleArn格式化,然后执行请求: 这被简化了,因为真正的实现验证了凭据变量等。它与AWS D

  • Spring Boot应用程序中的Websocket-获得403禁止 当我在eclipse中运行时,我可以使用sockjs/stompjs从客户机连接到websocket(没有Spring Boot)。 但是当我为websocket代码创建一个Spring boot jar(gradlew build)并运行java-jar websocket-code.jar时,我在连接到websocket时出

  • 问题内容: 我正在尝试以客户端/服务器方式制作Java应用程序。客户端是SWT中的GUI,它显示来自服务器的数据。服务器已连接到数据库。 好的,对此感到抱歉,我确定这是一个经典问题,但我不知道如何开始。 在我为他们工作的一个项目中,他们实施了很多魔术来透明地调用Glassfish服务器。 我不想使用Glassfish服务器。我只想要简单的Java语言。但是代理的概念似乎很酷。 你有这种想法或例子吗

  • 在调用writeAndFlush()之后,我不知道如何从服务器检索响应;我该怎么办? 我也使用Netty 4.0.18.final