GAE/Javaにアプリケーションをデプロイして、独自ドメインも割り当てて、動かしてみたのです。
とりあえず動くのですが、httpsではないので、Chromeが「保護されていません」と文句を言います。
なので、http接続だったらhttpsにリダイレクトしたかったのです。
Spring Securityを有効化する
Spring Securityを有効化するとデフォルトでhttpをhttpsにリダイレクトするらしいです。
当然ですが、Spring Security は有効化しているつもりです。
もしかして、これだけじゃ有効化できてなかったりします???
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
そもそも、Http Strict Transport Securityはデフォルトで有効化されていると、Spring Securityのドキュメントに書かれているのに、
サイトにアクセスしてもStrict Transport Securityヘッダーが存在しないんですよね。
pom.xmlに上記のdependencyを追加するだけではStrict Transport Securityヘッダーが追加されないんでしょうか?
なぜなのか。
app.yamlで設定する
で、「app engine http https redirect」ぐぐったら、一番たくさんでてきるのが、app.yamlでの設定です。
≫ https://cloud.google.com/appengine/docs/standard/reference/app-yaml?hl=ja&tab=java
src/main/appengine/app.yaml
handlers: - url: /.* secure: always script: auto
やってみたんですが、デプロイでエラーになりました。
ERROR: (gcloud.app.deploy) INVALID_ARGUMENT: WEB-INF/appengine-web.xml is required for this runtime.
appengine-web.xml を作ってデプロイしなおしたら、「404 not found」エラーです。
なぜなのか。
なんとなく、appengine-web.xmlを設置すると、web.xmlを参照して、URLとサーブレットの対応で処理してるっぽい動きです。
Spring BootなのでアノテーションでURLとコントローラーのメソッドを対応付けていますが、それが全部無視されてしまってる?
SecurityConfigでStrict Transport Securityヘッダーを設定する
Spring Securityの公式ドキュメントにしたがって、Strict Transport Securityヘッダーを付加するコードを追加してみました。
https://docs.spring.io/spring-security/site/docs/5.3.9.RELEASE/reference/html5/#headers-hsts
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.headers( headers -> headers .httpStrictTransportSecurity( hsts -> hsts .includeSubDomains(false) .maxAgeInSeconds(31536000) .preload(true))); return http.build(); } }
公式ドキュメントに書いてあるとおりにやってみたんですが、Strict Transport Securityヘッダーは追加されてません。
なぜなのか。
別の方法をぐぐってみます。
web.xmlでStrict Transport Securityヘッダーを設定する
web.xmlファイルでそれを指定する方法もあるみたいです。
<?xml version="1.0" encoding="utf-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <security-constraint> <web-resource-collection> <web-resource-name>HTTPS Redirect</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> </web-app>
やってみたけど、何も変わらないんですよね。
Strict Transport Securityヘッダーを設定する
Spring Securityの公式ドキュメントには、以下の方法も書かれてます
Strict Transport Securityヘッダーを追加する方法です。
公式ドキュメントに掲載されているこのコードを追加してみたら、HTTPSにリダイレクトされました!!
そして、ERR_TOO_MANY_REDIRECTSが発生。
なぜかのか。
https://spring.pleiades.io/spring-security/reference/servlet/exploits/http.html
@Configuration @EnableWebSecurity public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // ... .requiresChannel(channel -> channel .anyRequest().requiresSecure() ); return http.build(); } }
解決
シンプルに考えてみることにしました。
要するに、Strict Transport Securityヘッダーが付けばいいんだから、普通の手順でヘッダーを追加すればいいのでは?
https://www.techiedelight.com/ja/add-custom-header-to-all-responses-spring-boot/
@Component public class HstsFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { response.addHeader("Strict-Transport-Security", "max-age=31536000"); filterChain.doFilter(request, response); } }
これで、いい感じに動いてくれました。
ていうか、Spring Securityの公式ドキュメントが信用できないってどうよ。
なにか大切なことを読み落としてる可能性はあるんだけど。