Spring Boot 1.5.x の Web アプリを 2.0.x へバージョンアップする ( その7 )( src/main/resources/static の下の css や js ファイルにアクセスできない原因とは? )
概要
記事一覧はこちらです。
Spring Boot 1.5.x の Web アプリを 2.0.x へバージョンアップする ( その6 )( FindBugs 3.0.1 → SpotBugs 3.1.7 に切り替える ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
参照したサイト・書籍
Serving static web resources in Spring Boot & Spring Security application
https://stackoverflow.com/questions/24916894/serving-static-web-resources-in-spring-boot-spring-security-application/24920752Security changes in Spring Boot 2.0 M4
https://spring.io/blog/2017/09/15/security-changes-in-spring-boot-2-0-m4Spring MVC 5 - Static resources handling example
https://www.boraji.com/spring-mvc-5-static-resources-handling-example
目次
- Spring Boot 1.5 の時と 2.0 の時の CSS のリクエスト・レスポンスを比較してみる
- src/main/resources/static の下のファイルにアクセスできない原因を調査・解消する
- src/main/resources/static の下のファイルにキャッシュ期間を設定する
手順
Spring Boot 1.5 の時と 2.0 の時の CSS のリクエスト・レスポンスを比較してみる
1.5 の時はログイン画面は正常に表示されていたので、1.5 の時と 2.0 の時の CSS のリクエスト・レスポンスを比較してみます。まずは 2.0 から。
Tomcat を起動して DevTools を起動した Chrome で http://localhost:8080/ にアクセスすると、コンソールに MIME が text/html
になっているというエラーメッセージが表示されています。
Refused to apply style from '<URL>' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
Refused to execute script from 'http://localhost:8080/' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
Fiddler でログイン画面表示時のキャプチャを取得し、/css/bootstrap.min.css のリクエスト・レスポンスを見てみると、以下のようになっていました。
HTTP/1.1 302 X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY Location: http://localhost:8080/ Content-Length: 0 Date: Sat, 29 Sep 2018 00:18:08 GMT
HTTPステータスコードが 302 で Location: http://localhost:8080/
ヘッダが返ってきていました。なぜかリダイレクトされています。。。
次に 1.5 の時を見てみます。master ブランチへ切り替えてから build し直して Tomcat を起動し、ブラウザでアクセスします。画面も正常に表示され、コンソールには何も表示されていません。
Fiddler で /css/bootstrap.min.css のリクエスト・レスポンスを見てみると、以下のようになっていました。
HTTP/1.1 200 Last-Modified: Sat, 29 Sep 2018 10:35:37 GMT Cache-Control: no-store Accept-Ranges: bytes Content-Type: text/css Content-Length: 117309 Date: Sat, 29 Sep 2018 10:44:10 GMT
HTTPステータスコードは 200 が返ってきます。
状況は分かったので 2.0 の作業用ブランチに戻します。Spring Boot 1.5+Spring Security の構成の時には src/main/resources/static の下のファイルにアクセスできた(200 が返ってきていた)のですが、Spring Boot 2.0+Spring Security の構成だとアクセスできなくなっているようです。
src/main/resources/static の下のファイルにアクセスできない原因を調査・解消する
stackoverflow で Serving static web resources in Spring Boot & Spring Security application という QA を見つけました。
この中の回答によると、1.5 以下では public/** or static/**
がデフォルトで許可されていましたが、2.0 ではデフォルトで全て許可されなくなったそうです。
src/main/java/ksbysample/webapp/lending/config/WebSecurityConfig.java の以下の点を変更します。
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します // .antMatchers("/country/**").permitAll() .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() .antMatchers("/fonts/**").permitAll() ..........
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
を追加します。
Tomcat を起動してブラウザでアクセスすると、今度は画面が正常に表示されました。
Fiddler で見ると HTTPステータスコードの 200 が返ってきています。
HTTP/1.1 200 Last-Modified: Sat, 29 Sep 2018 23:28:18 GMT Accept-Ranges: bytes X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY Content-Type: text/css Content-Length: 117309 Date: Sat, 29 Sep 2018 23:34:21 GMT
src/main/resources/static の下のファイルにキャッシュ期間を設定する
※以降の変更はコミットはしません。
src/main/resources/static の下のファイルにアクセスできるようになりましたが、Cache-Control: no-cache, no-store, max-age=0, must-revalidate
等の HTTP ヘッダが付いていてキャッシュが無効になっています。css や js はキャッシュを設定したいことがあるので、設定してみます。
src/main/java/ksbysample/webapp/lending/config/WebMvcConfig.java に addResourceHandlers メソッドを override して設定します。
package ksbysample.webapp.lending.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.CacheControl; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.thymeleaf.spring5.SpringTemplateEngine; import java.util.concurrent.TimeUnit; /** * ??? */ @Configuration public class WebMvcConfig implements WebMvcConfigurer { /** * Thymeleaf 3 のパフォーマンスを向上させるために SpEL コンパイラを有効にする * * @param templateEngine {@link SpringTemplateEngine} オブジェクト */ @Autowired public void configureThymeleafSpringTemplateEngine(SpringTemplateEngine templateEngine) { templateEngine.setEnableSpringELCompiler(true); } /** * css, js のキャッシュ期間を設定する(css は 1時間、js は 15分) * * @param registry {@link ResourceHandlerRegistry} オブジェクト */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/css/**") .addResourceLocations("classpath:/static/css/") .setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic()); registry.addResourceHandler("/js/**") .addResourceLocations("classpath:/static/js/") .setCacheControl(CacheControl.maxAge(15, TimeUnit.MINUTES).cachePublic()); } }
Tomcat を起動して css, js のレスポンスを見るとキャッシュ期間が設定されていることが確認できます。
/css は Cache-Control: max-age=3600, public
とキャッシュ期間が1時間で設定されています。
HTTP/1.1 200 Last-Modified: Sat, 29 Sep 2018 23:28:18 GMT Cache-Control: max-age=3600, public Accept-Ranges: bytes X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block X-Frame-Options: DENY Content-Type: text/css Content-Length: 117309 Date: Sun, 30 Sep 2018 00:20:13 GMT
/js は Cache-Control: max-age=900, public
とキャッシュ期間が15分で設定されています。
HTTP/1.1 200 Last-Modified: Sat, 29 Sep 2018 23:28:18 GMT Cache-Control: max-age=900, public Accept-Ranges: bytes X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block X-Frame-Options: DENY Content-Type: application/javascript Content-Length: 84349 Date: Sun, 30 Sep 2018 00:20:13 GMT
履歴
2018/09/30
初版発行。