Spring 启动 - 无法通过 Zuul 代理获得 Keycloak 授权的响应 api

Spring Boot - Unable to get response of Keycloak authorized api via Zuul proxy

我为我的应用程序使用 spring 引导微服务和 docker。我已经通过 Zuul 代理公开了所有端点。而且我还使用 keycloak 来保护我的 api 端点。我在 application.properties 文件中配置如下所示。目前我无法获得使用 keycloak.securityConstraints.

授权的微服务 api 的响应

请注意,我还将 docker0 的子网和网关更改为 169.254.0.1/24169.254.0.1。请找到我的应用程序的以下文件。

docker-compose.yml 没有指定子网

version: "3"
services:
    eureka-naming-server:
        image: eureka-naming-server
        ports:
            - "8761:8761"
        container_name: eureka-naming-server
    zuul-proxy-service:
        image: zuul-proxy-service
        ports:
            - "8765:8765"
        links:
            - eureka-naming-server
        container_name: zuul-proxy-service
    user-service:
        image: user-service
        ports:
            - "8082:8082"
        links:
            - eureka-naming-server
        container_name: user-service
    keycloak:
        image: jboss/keycloak
        container_name: keycloak
        environment:
            KEYCLOAK_USER: user
            KEYCLOAK_PASSWORD: user_password
        ports:
            - 8080:8080

docker-compose.yml 指定默认子网

version: "3"
services:
    eureka-naming-server:
        image: eureka-naming-server
        ports:
            - "8761:8761"
        container_name: eureka-naming-server
    zuul-proxy-service:
        image: zuul-proxy-service
        ports:
            - "8765:8765"
        links:
            - eureka-naming-server
        container_name: zuul-proxy-service
    user-service:
        image: user-service
        ports:
            - "8082:8082"
        links:
            - eureka-naming-server
        container_name: user-service
    keycloak:
        image: jboss/keycloak
        container_name: keycloak
        environment:
            KEYCLOAK_USER: user
            KEYCLOAK_PASSWORD: user_password
        ports:
            - 8080:8080
networks:
    default:
        ipam:
            config:
                - subnet: "169.254.3.0/24"
Zull代理的

application.yml

server:
  port: 8765

eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka-naming-server:8761/eureka/
  instance:
    prefer-ip-address: true
    metadataMap:
      instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
    instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}

zuul:
  prefix: /api
  sensitive-headers:
  add-proxy-headers: false
  routes:
    user-service:
      path: /user/**
      service-id: USER-SERVICE

application.yml 共 user-service

spring.application.name=user-service
keycloak.realm=master
keycloak.resource=my-client
keycloak.auth-server-url=http://<ip>/auth
keycloak.public-client=true
keycloak.principal-attribute=preferred_username
keycloak.securityConstraints[0].authRoles[0]=admin
keycloak.securityConstraints[0].securityCollections[0].patterns[0]=/change-password

这是我的问题

1) 当我不使用 zuul 代理时(即 http//:8082/change-password)我可以使用有效的密钥斗篷令牌成功获得响应。但是当使用 http//:8765/api/user/change-passworddocker-compose.yml 指定默认子网时 我不能得到回应。

我总是收到以下响应 headers,有效令牌状态为 200。

 cache-control: private 
 date: Wed, 21 Aug 2019 11:02:02 GMT 
 expires: Thu, 01 Jan 1970 00:00:00 GMT 
 transfer-encoding: chunked

并在 user-service 日志中创建以下日志。

2019-08-21 03:18:26.191  WARN [-,,,] 1 --- [nio-8087-exec-2] o.k.adapters.RequestAuthenticator        : SSL is required to authenticate. Remote address 169.254.0.4 is secure: false, SSL required for: EXTERNAL .

然而,当我使用无效令牌时,出现 401 错误(正如预期的那样)。

我需要使用路由过滤器来解决这个问题吗???

任何帮助将不胜感激!

似乎所有外部请求都需要 SSL。这可以设置,例如通过 Realm Settings -> Login -> Require SSL (https://www.keycloak.org/docs/5.0/server_admin/index.html#_ssl_modes) 中的管理控制台。 出于测试目的,您可以尝试将其设置为 None。永远不要在生产系统上这样做。

可以为客户端做同样的事情(在用户服务的 application.yml 中):

keycloak.ssl-required = none

(https://www.keycloak.org/docs/latest/securing_apps/index.html#_java_adapter_config)

我也 运行 在使用具有 keyloak 集成的代理后面的微服务的反向代理时遇到这个问题。错误的原因是来自 keycloak 的某种安全实现检查反向代理提供的 X-Forward headers。它在 documentation 中有详细解释,但老实说,我并不真正理解为什么需要它。因此,消除此错误的一个简单解决方案是简单地丢弃 X-Forward headers,这会使请求看起来像内部请求。

在祖尔:

zuul:
  add-proxy-headers: false

在 Spring 云网关中:

spring:
  cloud:
    gateway:
      x-forwarded:
        port-enabled: false
        host-enabled: false
        proto-enabled: false
        port-append: false
        host-append: false
        proto-append: false
        enabled: false

在反向代理后面的每个微服务上设置keycloak.ssl-required可能也可以,但我没有尝试过。我更喜欢只在一个地方进行配置。