web-dev-qa-db-ja.com

リバースプロキシの背後にあるSpringSecurityでHTTPSを要求する

SpringSecurityで保護されたSpringMVCアプリケーションがあります。アプリケーションの大部分は単純なHTTPを使用してリソースを節約しますが、一部はより機密性の高い情報を処理し、HTTPSチャネルを必要とします。

_security-config.xml_からの抜粋:

_<sec:http authentication-manager-ref="authenticationManager" ... >
    ...
    <sec:intercept-url pattern="/sec/**" requires-channel="https"/>
    <sec:intercept-url pattern="/**" requires-channel="http"/>
</sec:http>
_

アプリケーションサーバーがリバースプロキシの背後で実行されるメインサーバーに移行することを決定するまで、すべて正常に機能しました。また、HTTPSはリバースプロキシによって処理されるため、アプリケーションサーバーはHTTPリクエストのみを認識し、_/sec/**_階層へのアクセスを許可しません。

調査の結果、プロキシが_X-Forwarded-Proto: https_ヘッダーを追加していることがわかりました。 (*)、ただしSpring SecurityではHttpServletRequest.isSecure()は、提供されるチャネルセキュリティを決定するために使用されますSecureChannelProcessor javadocから抽出)。

_X-Forwarded-Proto: https_ヘッダーが安全なリクエストに十分であることをSpring Securityに伝えるにはどうすればよいですか?

プロキシ構成についてその部分を報告できることは知っていますが、プロキシの背後には多くのアプリケーションがあり、構成が管理不能な状態になる可能性があるため、プロキシ管理者は実際にはそのソリューションを好みません。

現在、XML構成でSpring Security 3.2を使用していますが、Java configおよび/または最新バージョンに基づく回答を受け入れる準備ができています。

(*)もちろん、プロキシはヘッダーが着信要求に存在する場合はヘッダーを削除するため、アプリケーションはヘッダーに自信を持つことができます。

14
Serge Ballesta

サイトがHTTPSであり、TLS終了を処理する別のシステムの背後でApache Tomcatを実行している場合は、TLS終了を処理しているように「見せかける」ようにTomcatに指示できます。

これにより、request.isSecure()trueを返します。

これを行うには、secure="true"のコネクタ構成にserver.xmlを追加する必要があります。

https://Tomcat.Apache.org/Tomcat-7.0-doc/config/http.html

scheme属性も参照してください。

5
Neil McGuigan

解決策がサーブレットコンテナ側であることを示したNeilMcGuiganの回答に対する一種のフォローアップ。

Tomcatはさらに優れています。リバースプロキシの副作用マスキング専用のバルブがあります。 リモートIPバルブ のTomcatドキュメントからの抜粋:

このValveのもう1つの機能は、見かけのスキーム(http/https)、サーバーポート、およびrequest.secureを、リクエストヘッダーを介してプロキシまたはロードバランサーによって提示されるスキームに置き換えることです(例: " X-Forwarded-Proto ")。

バルブ構成の例:

_<Valve className="org.Apache.catalina.valves.RemoteIpValve"
    internalProxies="192\.168\.0\.10|192\.168\.0\.11"
    remoteIpHeader="x-forwarded-for" proxiesHeader="x-forwarded-by"
    protocolHeader="x-forwarded-proto" />
_

そうすればアプリケーション自体の他の構成がない場合、リクエストに次のヘッダーフィールドが含まれている場合、Request.isSecure()の呼び出しはtrueを返します。 _X-Forwarded-Proto=https_。

私は他に2つの可能性を考えていましたが、間違いなくその1つを好みます。

  • spring Security ChannelProcessingFilterの前にアクティブなフィルターを使用してリクエストをHttpServletRequestWrapperでラップし、isSecure()をオーバーライドして_X-Forwarded-Proto_ヘッダーを処理します-フィルターの作成とテストが必要ラッパー
  • spring BeanPostProcessorを使用してChannelProcessingFilterを探し、_X-Forwarded-Proto_ヘッダーを考慮できるChannelDecisionManagerを手動で挿入します-レベルが低すぎます
19
Serge Ballesta

Spring Bootはそれを非常にシンプルにします(少なくとも組み込みTomcatでは)。

1。次の行をapplication.propertiesに追加します:

server.forward-headers-strategy=native
server.Tomcat.remote-ip-header=x-forwarded-for
server.Tomcat.protocol-header=x-forwarded-proto

2。 HttpSecurity構成で次のトリックを実行します。

// final HttpSecurity http = ...
// Probably it will be in your `WebSecurityConfigurerAdapter.configure()`

http.requiresChannel()
            .anyRequest().requiresSecure()

ソースはSpring Bootリファレンスガイドです

84.3プロキシサーバーの背後で実行しているときにHTTPSを有効にする

Spring Boot 2.2に関連する詳細 については、以下の回答も確認してください。

10