【问题标题】:Keycloak behind apache reverse proxyApache反向代理背后的Keycloak
【发布时间】:2017-07-09 14:28:00
【问题描述】:

我在谷歌上冲浪没有找到任何具体答案或示例,所以再次在这里试试运气(经常走运)。

问题

  • 我有一个 Spring Boot RESTful 服务在 Apache 后面运行 反向代理。此 RESTful 服务仅运行 HTTP。说它正在运行 本地ip 172.s 8080端口。

  • 我还配置了一个 apache 反向代理。说它正在运行 本地 ip 172.a 和公共 ip 55.a。此代理同时响应 80 端口,但所有 HTTP 流量都自动重定向到 443。

  • 我有另一台服务器运行独立的 Keycloak 服务器。还 此服务器配置为可通过 反向代理。假设它在本地 ip 172.k 上运行。此 Keycloak 服务器仅在 HTTP 上运行。 HTTP 请求通过反向代理使用 SSL 进行处理。

  • 最后,我在本地 ip 172.f 上运行了另一个前端 web 应用程序。这个 frontend-webapp 在 Nodejs 下运行,也是通过反向代理配置的。它也只运行 HTTP,但客户端(浏览器)通过反向代理使用 SSL,就像 Keycloak 和 RESTful 服务一样。此前端正在使用 RESTful 服务,并且还配置为使用 keycloak javascript 适配器进行身份验证。

  • RESTful 服务使用 Spring Boot Keycloak 适配器配置为仅承载,而前端应用程序配置为公共访问类型。

RESTful 服务服务器、Keycloak 服务器和前端服务器不可公开访问;它们只能通过反向代理访问。但是它们可以相互通信(因为它们在同一个专用网络中)。

在前端keycloak.json文件中,auth-server-url设置为代理urlhttps://example.com/auth,前端能够成功获取到有效token。现在,当我尝试使用 RESTful 服务时,我在 RESTful 适配器中收到一个错误,即令牌颁发者无效。当然,我在 http-header 中发送Authorization: Bearer <token>。我收到此错误的原因是在 RESTful keycloak 配置中,我已将 auth-server-url 配置为使用本地 url http://172.k:9080/auth,因此此 url 与令牌中的 URL 不同(即 https://example.com/auth)。

问题

我不能在 RESTful 服务中包含与前端相同的 auth-server-url,因为这将要求我还在 RESTful 服务上设置 HTTP(因为 url 是 https),这会使事情复杂化很多,包括需要设置证书和类似的东西。另外我认为在本地服务器上设置 SSL 效率低且不实用。

所以我的问题是如何让适配器在不通过反向代理的情况下与 Keycloak 对话。我希望 RESTful 适配器通过 auth-server-url: http://172.k:9080/auth 与 Keyclok 服务器通信以进行令牌验证。

之前有一个不同的后端网址,已被删除:https://issues.jboss.org/browse/KEYCLOAK-2623

【问题讨论】:

  • 您是否尝试将 Web Origins 设置为 *.如果我是对的,我通过跨域访问遇到了同样的问题
  • 是的,我尝试将 Web-origins 设置为 '*',但没有成功。

标签: reverse-proxy keycloak


【解决方案1】:

您需要告知 keycloak 反向代理的位置。然后在它的响应中它将位置设置到那里而不是它的本地地址。为此,在最新的 keycloak 中设置环境变量 KEYCLOAK_FRONTEND_URL 指向 字符串https://example.com/auth(是的,它需要整个地址。 要完成这项工作,还要将 PROXY_ADDRESS_FORWARDING 设置为值 true

如果是 Docker 容器,则意味着:

environment:
  ...
  PROXY_ADDRESS_FORWARDING: "true"
  KEYCLOAK_FRONTEND_URL: "https://example.com/auth"

或者,您可以将KEYCLOAK_HOSTNAME 设置为example.com,这将留下端口号,用于哪个???(不确定如何执行此部分,如果您发现请告诉我...) )

编辑:请注意,在某些情况下,您可能只想为特定客户端设置此项。在 keycloak 中配置每个客户端时,您可以从第一个选项选项卡中设置其 Frontend_URL。

【讨论】:

  • 谢谢。我将 - KEYCLOAK_FRONTEND_URL=keycloak:8080/auth 放入我的 docker-compose.yml 中,它就像一个魅力! openid 端点配置现在看起来可以使用了。
【解决方案2】:

其中一种解决方案是将适配器升级到 8.0.0。这个问题似乎在 8.0.0 版本中得到修复。

已知问题KEYCLOAK-6073:

向 Java 适配器添加对 OpenID Connect Discovery 的支持... 适配器应支持对前端和后端请求使用不同的 URL。

【讨论】:

  • 您好,请问可以提供样品吗?我很困惑如何使用新功能。谢谢!
【解决方案3】:

我在 docker swarm 环境中遇到过类似的问题。我的 Keycloak 和我的 Spring Boot 容器都在同一个反向代理之后。

对于 Tomcat: 问题是正确配置 http(s) 连接器。假设我们的反向代理的主机名和端口是 http://${EXTERNAL_HOSTNAME}:${EXTERNAL_PORT}。

那么 tomcat.xml 中的 http(s) 连接器应该有这两个附加属性:

<Connector [...] proxyName="${EXTERNAL_HOSTNAME}" proxyPort="${EXTERNAL_PORT}"/>

这将使所有对 servletRequest.getServerName() 和 servletRequest.getServerPort() 的调用都以我们的反向代理的值进行响应。 keycloak 适配器当然使用这些函数来确定重定向 url。

对于 Spring Boot:将这个类放到你的类路径中:

@Component
public class TomcatReverseProxyCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>, TomcatConnectorCustomizer {

    @Value("${server.tomcat.proxy-name}")
    private String proxyName;
    @Value("${server.tomcat.proxy-port}")
    private int proxyPort;

    @Override
    public void customize(final TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers(this);
    }

    @Override
    public void customize(final Connector connector) {
        connector.setProxyName(this.proxyName);
        connector.setProxyPort(this.proxyPort);
    }

}

然后在 application.properties 中设置:

server.tomcat.proxy-name=${EXTERNAL_HOSTNAME}
server.tomcat.proxy-port=${EXTERNAL_PORT}

keycloak 适配器的附加配置(以 Spring Boot 为例):

我的 keycloak 也在同一个反向代理后面。所以我还必须将 keycloak 适配器的身份验证服务器 url 设置为反向代理的主机名。然后我滥用 keycloak 适配器的代理设置,让它使用内部腿上的服务:

keycloak.auth-server-url=http://${EXTERNAL_HOSTNAME}:${EXTERNAL_PORT}/auth
keycloak.proxy-url=http://${INTERNAL_KEYCLOAK_HOSTNAME}:${INTERNAL_KEYCLOAK_PORT}/auth

这些设置也可能有意义:

server.servlet.session.cookie.domain=${EXTERNAL_HOSTNAME}
server.use-forward-headers=true
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto 

server.tomcat.protocol-header 对于那些在其反向代理上终止 SSL 的人来说很重要。

【讨论】:

    【解决方案4】:

    我正在将 Keycloak 用于 docker 容器中的项目。我遇到了同样的问题,但在本地网络中(所以也许这不是解决方案,在这种情况下我很抱歉)。原来是这样的:

    • 在 Wildfly 上运行的 REST java webapp,在单个 Docker 容器中
    • Keycloak 运行在与之前相同的网络中的单个 Docker 容器中
    • Apache 在 Docker 外部的机器上本地运行,提供 angular 2 应用程序,配置正确

    • angular 2 应用程序的适配器指向 url http://aaa.auth.com(我使用条目 127.0.0.1 aaa.auth.com 修改了本地文件主机)

    • 我通过主机名http://aaa.auth.com 在 Wildfly Docker 和 Keycloak Docker 之间添加了一个链接,并且我在 Java webapp 适配器中使用了这个主机名。
    • 两个适配器都指向同一个地址,据我所知这是 Keycloak 要求,请参阅https://issues.jboss.org/browse/KEYCLOAK-2067

    与您的情况(Docker、HTTP 与 HTTPS 等)有很多不同,但是,为了避免通过 Web 通信 REST-Keycloak,您是否尝试过修改服务器的文件主机(托管 RESTful 服务)插入带有您的反向代理 (172.a) 和“example.com”的本地 IP 的条目?

    或者,也许您可​​以使用私有 DNS 解决它?

    【讨论】:

      【解决方案5】:

      我尝试了不同的方法,但无法解决问题。对我来说,似乎没有办法在后端适配器中指定 auth-server-url: http://172.k:9080/auth 而前端适配器将 auth-server-url:https://example.com/auth 放入令牌中。所以我的解决方案是将所有后端服务也配置为auth-server-url: https://example.com/auth

      唯一的缺点是我的后端服务适配器通过 web 与 keycloak 通信,这在性能方面可能不太好,但至少一切正常。应该可以在同一个本地网络或 AWS 中的同一个 VPN 中以某种方式指定一个本地 keycloak 端点。

      【讨论】:

      • 致读者:如果您有其他解决方案,请务必提供答案,我很乐意接受我们的回答。
      • 这太可悲了:( 数据或带宽很昂贵,因此通过公共网络是一个很大的浪费......
      • 我也在为此苦苦挣扎。我正在尝试将我的 keycloak-server 迁移到新的 URL,而后端位于同一 URL。我所有的手机应用程序都需要一些时间来更新并开始使用新的 URL。所以与此同时,我需要在我的后端适配器中接受这两个 URL。
      猜你喜欢
      • 2017-01-23
      • 1970-01-01
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 2022-01-22
      • 2019-06-13
      • 2019-03-14
      相关资源
      最近更新 更多