如何在@WebFluxTest 中禁用 oauth2 客户端注册?

Posted

技术标签:

【中文标题】如何在@WebFluxTest 中禁用 oauth2 客户端注册?【英文标题】:How to disable oauth2 client registration in @WebFluxTest? 【发布时间】:2021-07-13 09:56:33 【问题描述】:

已配置 oauth2:

security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: $keycloak.server-url/realms/$keycloak.realm
      client:
        provider:
          keycloak:
            issuer-uri: $keycloak.server-url/realms/$keycloak.realm
            user-name-attribute: email
        registration:
          keycloak:
            client-id: $keycloak.client-id
            client-secret: $keycloak.client-secret
            scope: openid

我想知道如何为控制器运行 @WebFluxTest 而无需运行实际的 keycloak 服务器。当我运行本地 keycloak 服务器时,以下测试运行良好:

@WebFluxTest(TaskController::class)
class TaskControllerTest 

  @Autowired
  private lateinit var client: WebTestClient

  @MockkBean
  private lateinit var taskService: TaskServiceImpl

  @Test
  @WithMockUser(roles = ["user"])
  fun getByIds() 
    val ids = setOf<Long>(1, 2)
    every  taskService.getByIds(ids, any())  returns flowOf(
      TaskWithRating(
        Task(
          id = 1,
          title = "title",
          description = "desc"
        ),
        Rating(0, 0),
      )
    )
    client
      .get()
      .uri  uriBuilder ->
        uriBuilder
          .path("/tasks/byIds")
          .queryParam("ids", ids)
          .build()
      
      .exchange()
      .expectStatus().isOk
      .expectBody()
      .jsonPath("$.length()").isEqualTo(1)
      .jsonPath("$.1.task.id").isEqualTo(1)
  

当我停止本地 keycloak 服务器时,测试失败,因为 spring 在启动期间尝试读取 oauth2 配置,同时创建 ApplicationContext:

Failed to load ApplicationContext
...
Factory method 'clientRegistrationRepository' threw exception; nested exception is java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of "https://keycloak.local.com/auth/realms/myrealm"
...
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://keycloak.local.com/auth/realms/myrealm/.well-known/openid-configuration": Connection refused; nested exception is java.net.ConnectException: Connection refused
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:784)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:669)
    at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:156)
    at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:209)
    ... 175 more
Caused by: java.net.ConnectException: Connection refused

测试不需要它,因为无论如何都会模拟用户。所以我想在@WebFluxTest 中禁用 auth2 配置,但我不知道这是如何以及是否是一种有效的方法?

我试过了。

@WebFluxTest(
  controllers = [TaskController::class],
  excludeAutoConfiguration = [ReactiveSecurityAutoConfiguration::class],
)

还有这个

@WebFluxTest(
  controllers = [TaskController::class],
  excludeAutoConfiguration = [ReactiveOAuth2ClientAutoConfiguration::class],
)

但错误是一样的。

【问题讨论】:

【参考方案1】:

事实证明我是在正确的道路上。必须禁用 oauth2 客户端和资源服务器自动配置。这有效:

@WebFluxTest(
  controllers = [TaskController::class],
  excludeAutoConfiguration = [
    ReactiveOAuth2ClientAutoConfiguration::class,
    ReactiveOAuth2ResourceServerAutoConfiguration::class,
  ],
)

请注意,这会绕过可能禁用的功能,因此,例如,需要在测试客户端上进行 csrf() 突变:

client
  .mutateWith(SecurityMockServerConfigurers.csrf()) 

对此的替代方法是使用@Import(TestSecurityConfiguration::class) 为安全设置配置测试配置。

【讨论】:

以上是关于如何在@WebFluxTest 中禁用 oauth2 客户端注册?的主要内容,如果未能解决你的问题,请参考以下文章

如何 WebFluxTest 白色 ReactiveSecurityContextHolder

如何使用 Spring Security @Secured 注解测试 Spring Boot @WebFluxTest

我们如何禁用 /oauth/token 的 GET 选项端点,并且只在 Spring Security 中保留 POST 选项?

从“@WebFluxTest”迁移到“@SpringBootTest”后,集成测试中的连接被拒绝

Spring Boot 1.5 禁用 oauth2 安全性

在 Spring Cloud Gateway 的 oauth2 客户端流中禁用重定向到 oauth2/authorization/registrationId