私はconcreteの答えやexamplesを見つけることなくグーグルをサーフィンしたのでここでもう一度私の運を試します(しばしば幸運になります)。
問題
Apacheリバースプロキシの背後で実行されている単一のスプリングブートRESTfulサービスがあります。このRESTfulサービスはHTTPのみを実行しています。ローカルIP172.sポート8080で実行されているとします。
Apacheリバースプロキシも設定しました。ローカルIP172.aとパブリックIP55.aで実行されているとします。このプロキシは両方のポート80に応答しますが、すべてのHTTPトラフィックは自動的に443にリダイレクトされます。
スタンドアロンのKeycloakサーバーを実行している別のサーバーがあります。また、このサーバーは、リバースプロキシを介してパブリックアクセスできるように構成されています。ローカルIP172.kで実行されているとします。このKeycloakサーバーはHTTPのみで実行されています。 HTTPリクエストは、リバースプロキシ経由でSSLを使用して処理されます。
最後に、ローカルIP172.fで実行されている別のフロントエンドwebappがあります。このfrontend-webappはNodejsで実行されており、リバースプロキシを介して構成されています。また、HTTPのみを実行していますが、クライアント(ブラウザー)は、KeycloakおよびRESTfulサービスの場合と同様に、リバースプロキシを介してSSLを使用しています。このフロントエンドはRESTfulサービスを使用しており、keycloakjavascriptアダプターを使用して認証するようにも構成されています。
RESTfulサービスは、Spring Boot Keycloakアダプターを使用してベアラーのみとして構成されますが、フロントエンドアプリはアクセスタイプpublicで構成されます。
RESTfulサービスサーバー、Keycloakサーバー、およびフロントエンドサーバーはパブリックアクセスできません。それらはリバースプロキシを介してのみアクセス可能です。ただし、それらは互いに通信できます(同じプライベートネットワーク内にあるため)。
フロントエンドのkeycloak.jsonファイルでは、auth-server-url
がプロキシURLhttps://example.com/auth
に設定されており、フロントエンドは有効なトークンを正常に取得できます。これで、RESTfulサービスを利用しようとすると、トークン発行者が無効であるというエラーがRESTfulアダプターで発生します。もちろん、http-headerではAuthorization: Bearer <token>
を送信しています。このエラーが発生する理由は、RESTfulキークローク構成で、ローカルURL auth-server-url
を使用するようにhttp://172.k:9080/auth
を構成したため、このURLがトークン内のURL(https://example.com/auth
)と異なるためです。
質問
フロントエンドと同じauth-server-url
をRESTfulサービスに含めることはできません。RESTfulサービスでHTTPSも設定する必要があり(URLがhttpsであるため)、証明書を設定する必要があるなど、非常に複雑になります。そしてそのようなもの。また、ローカルのみのサーバーでSSLを設定するのは非効率的で実用的ではないと思います。
だから私の質問は、リバースプロキシを経由せずにアダプタがKeycloakと通信できるようにする方法です。 RESTfulアダプターがauth-server-url: http://172.k:9080/auth
を介したトークン検証のためにKeyclokサーバーと通信するようにしたい。
以前はバックエンドに別のURLがあり、削除されました: https://issues.jboss.org/browse/KEYCLOAK-262
別のことを試しましたが、問題を解決できませんでした。私には、フロントエンドアダプタがトークンに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内でローカルキークロークエンドポイントを何らかの方法で指定することが可能であったはずです。
DockerコンテナのプロジェクトにKeycloakを使用しています。私は同じ問題を抱えていましたが、ローカルネットワークで発生しました(したがって、これは解決策ではない可能性があります。この場合は申し訳ありません)。だからこれは状況でした:
Dockerの外部の私のマシンでローカルに実行されているApacheは、適切に構成されたangular 2アプリを提供します
angular 2アプリのアダプターがURLを指していました http://aaa.auth.com (ローカルファイルホストをエントリ127.0.0.1aaa.authで変更しました.com)
あなたの場合(Docker、HTTP対HTTPSなど)とは多くの違いがありますが、Web経由のREST-Keycloakの通信を避けるために、サーバーのファイルホスト(RESTfulサービスをホストする)を変更して、エントリを挿入してみましたか?リバースプロキシ(172.a)と「example.com」のローカルIP?
または、プライベートDNSで解決できるかもしれません。
DockerSwarm環境でも同様の問題が発生しました。 KeycloakとSpringBootコンテナは、どちらも同じリバースプロキシの背後にありました。
Tomcatの場合:問題はhttp(s)コネクタを正しく設定することです。リバースプロキシのホスト名とポートがhttp:// $ {EXTERNAL_HOSTNAME}:$ {EXTERNAL_PORT}であるとしましょう。
次に、Tomcat.xmlのhttp(s)コネクタには、次の2つの追加属性が必要です。
<Connector [...] proxyName="${EXTERNAL_HOSTNAME}" proxyPort="${EXTERNAL_PORT}"/>
これにより、servletRequest.getServerName()およびservletRequest.getServerPort()へのすべての呼び出しがリバースプロキシの値で応答します。キークロークアダプタは確かにこれらの関数を使用してリダイレクト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アダプターの認証サーバーの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を終了するユーザーにとって重要です。
解決策の1つは、アダプターを8.0.0にアップグレードすることです。この問題はバージョン8.0.0で修正されているようです。