Spring Securityで保護され、EC2で実行されるSpring Webアプリがあります。 EC2インスタンスの前にはSSL証明書を備えたElastic Load Balancer(httpsはロードバランサー、つまりポート443->ポート80で終了します)があるため、Tomcatの観点からは、インバウンドリクエストはHTTPです。
ログインフォームはhttpsに送信されますが、その後のリダイレクトはhttpに移動します(成功または失敗)。認証に成功し、httpsに戻ることができ、ログインしています。
私のログイン構成は次のようになります。
<security:form-login
default-target-url="/home"
login-page="/"
login-processing-url="/processlogin"
authentication-failure-url="/?login_error=1"/>
Default-target-urlとauthentication-failure-urlをhttpsにするには、何を変更する必要がありますか?
スプリングの構成は、使用するプロトコルに依存しない必要があります。 「requires-channel」などを使用すると、遅かれ早かれ問題が発生します。特に、httpsを使用せずに開発環境に同じアプリケーションをデプロイする場合は特にそうです。
代わりに、Tomcatを適切に構成することを検討してください。 RemoteIpValve でこれを行うことができます。ロードバランサーが送信するヘッダーに応じて、server.xml設定には次のようなものが含まれている必要があります。
<Valve
className="org.Apache.catalina.valves.RemoteIpValve"
internalProxies=".*"
protocolHeader="X-Forwarded-Proto"
httpsServerPort="443"
/>
SpringはServletRequestに基づいて絶対リダイレクトアドレスを決定するため、443以外のものを使用している場合はhttpsServerPortを変更します。
HttpsServerPortは、protocolHeaderがhttpsプロトコルを示すときにServletRequest.getServerPort()によって返されるポートです。
Spring Bootアプリケーションの場合(現在2.0.0リリースを使用しています)、application.properties
ファイルで十分です:
server.Tomcat.protocol-header=x-forwarded-proto
これは、AWSで前面にロードバランサーを使用して機能しました。
Spring Boot <2.0.0の場合も動作するはずです(テストされていません)
私がこれを機能させた1つの方法は、次の構成を追加することです
<http auto-config="true" use-expressions="true" entry-point-ref="authenticationEntryPoint" >
<form-login login-page="/login.jsf" authentication-failure-url="/login.jsf?login_error=t" always-use-default-target="true" default-target-url="xxxxx" />
<logout logout-url="/logout" logout-success-url="/logoutSuccess.jsf" />
...
</http>
always-use-default-target="true"
とdefault-target-url="https://...."
を追加する必要がありました。 configでURLをハードコーディングする必要があるため、理想的な方法ではありません。
Google Kubernetesの背後にあるSpring Bootでも同じ問題がありました。 application.propertiesにこれらの2行を追加すると、それができました
server.Tomcat.remote-ip-header=x-forwarded-for
server.Tomcat.protocol-header=x-forwarded-proto
web.xmlの以下のコード行を使用します
<security-constraint>
<web-resource-collection>
<web-resource-name>Login and Restricted Space URLs</web-resource-name>
<url-pattern>/j_security_check</url-pattern>
<url-pattern>/loginpage.rose</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
hTTPSの使用を強制します。
私の場合、プロパティを削除する必要がありましたserver.use-forward-headers=true
。
これは私のセットアップです:
Digital Ocean LB-> Ingressを使用したKubernetesクラスター-> Spring bootアプリケーション
すべてのintercept-urlでrequire-channel = "any"を設定します。これにより、SSLを使用しない開発環境でも引き続き機能します。
<intercept-url pattern="/createUser" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" requires-channel="any"/>
<intercept-url pattern="/**" access="isAuthenticated()" requires-channel="any"/>
次に、すべてのトラフィックをHTTPSバージョンにリダイレクトするApache仮想ホストを作成します。
<VirtualHost *:80>
ServerName www.mywebsite.com
Redirect permanent / https://www.mywebsite.com/
</VirtualHost>
私もまったく同じ問題に直面しており、適切な解決策が得られるまで、HTTPではなくAJPを介してプロキシサーバーからTomcatサーバーにリクエストをリダイレクトしています。以下は私のApache設定です
ProxyPass /myproject ajp://localhost:8009/myproject
ProxyPassReverse /myproject ajp://localhost:8009/myproject