[英]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 容器中的一个项目。 我有同样的问题,但在本地网络中(所以也许这不是解决方案,在这种情况下我很抱歉)。 所以情况是这样的:
Apache 在 Docker 之外的我的机器上本地运行,提供 angular 2 应用程序,并具有正确的配置
angular 2 应用程序的适配器指向 url http://aaa.auth.com (我用条目 127.0.0.1 aaa.auth.com 修改了本地文件主机)
与您的案例(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.