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および/または最新バージョンに基づく回答を受け入れる準備ができています。
(*)もちろん、プロキシはヘッダーが着信要求に存在する場合はヘッダーを削除するため、アプリケーションはヘッダーに自信を持つことができます。
サイトが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
属性も参照してください。
解決策がサーブレットコンテナ側であることを示した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つを好みます。
ChannelProcessingFilter
の前にアクティブなフィルターを使用してリクエストをHttpServletRequestWrapper
でラップし、isSecure()
をオーバーライドして_X-Forwarded-Proto
_ヘッダーを処理します-フィルターの作成とテストが必要ラッパーBeanPostProcessor
を使用してChannelProcessingFilter
を探し、_X-Forwarded-Proto
_ヘッダーを考慮できるChannelDecisionManager
を手動で挿入します-レベルが低すぎます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に関連する詳細 については、以下の回答も確認してください。