繁体   English   中英

apache反向代理背后的Keycloak

[英]Keycloak behind apache reverse proxy

我在谷歌上浏览过,没有找到任何具体的答案或例子,所以再次在这里碰碰运气(通常很幸运)。

问题

  • 我有一个在 apache 反向代理后面运行的 Spring Boot RESTful 服务。 此 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 上运行了另一个前端 webapp。 这个frontend-webapp是在Nodejs下运行的,也是通过反向代理配置的。 它也只运行 HTTP,但客户端(浏览器)通过反向代理使用 SSL,就像 Keycloak 和 RESTful 服务一样。 该前端使用 RESTful 服务,并且还配置为使用 keycloak javascript 适配器进行身份验证。

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

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

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

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

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

早些时候有一个不同的后端网址,被删除了: https : //issues.jboss.org/browse/KEYCLOAK-2623

我正在将 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 解决它?

我尝试了不同的东西,但无法解决问题。 对我来说,似乎没有办法在后端适配器中指定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。 然后在它的响应中,它会将 location 设置为那里而不是它的本地地址。 要在最新的 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。

我在 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 的人很重要。

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

已知问题KEYCLOAK-6073

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM