3

我尝试构建一个最小的 openid 安全云环境。或多或少遵循https://developer.okta.com/blog/2019/08/28/reactive-microservices-spring-cloud-gateway

我有一个 spring 云网关、一个领事注册表、一个在 okta 上注册的应用程序和一个简单的测试应用程序,只有一个控制器返回一个字符串。网关和测试应用程序都依赖于'com.okta.spring', name: 'okta-spring-boot-starter', version: '1.4.0'.

网关配置如下(为简洁起见,此处跳过 ssl):

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false
    gateway:
      default-filters: 
        - TokenRelay
      discovery:
        locator:
          enabled: true
okta:
  oauth2:
    issuer: ${OKTA_OAUTH2_ISSUER}
    client-id: ${OKTA_OAUTH2_CLIENT_ID}
    client-secret: ${OKTA_OAUTH2_CLIENT_SECRET}

我添加了一个最小的安全配置:

private final ReactiveClientRegistrationRepository clientRegistrationRepository;

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
    http
            .redirectToHttps()
            .and()
            .authorizeExchange()
            .pathMatchers("/login").permitAll()
            .pathMatchers("/actuator/**").permitAll()
            .anyExchange().authenticated()
            .and()
            .oauth2Login()
            .and()
            .logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler()))
            .oauth2ResourceServer()
            .jwt();
    return http.build();
}

private ServerLogoutSuccessHandler oidcLogoutSuccessHandler() {
    OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler =
            new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository);

    oidcLogoutSuccessHandler.setPostLogoutRedirectUri(URI.create("https://<my-uri>"));

    return oidcLogoutSuccessHandler;
}

测试应用程序还在 application.yml 中配置了 okta openid,就像在网关中一样:

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
    http
            .authorizeExchange()
            .pathMatchers("/actuator/**").permitAll()
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();

    Okta.configureResourceServer401ResponseBody(http);

    return http.build();
}

我的问题是:

当我删除令牌中继并使测试应用程序不安全时,网关将成功进行授权,并且响应包含一个set-cookie标头,该标头可用于后续请求以再次运行所有授权流程。

但是,通过'org.springframework.cloud:spring-cloud-starter-security'(并配置为默认过滤器,如上所示)添加令牌中继,会返回一个空的 set-cookie 标头,因此运行的每个请求都会抛出整个授权流程。

我尝试了不同的解决方案,例如手动配置ReactiveOAuth2AuthorizedClientService. 我的方法都更像是猜测。

4

1 回答 1

3

事实证明,解决方案是从下游请求中删除 cookie 标头。这可以通过向网关添加另一个默认过滤器来实现:

spring:
  cloud:
    gateway:
      default-filters: 
        - TokenRelay=
        - RemoveRequestHeader=Cookie
于 2020-04-06T13:49:03.520 回答