簡體   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