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の公式ドキュメントが信用できないってどうよ。
なにか大切なことを読み落としてる可能性はあるんだけど。