Spring Boot + Spring Security のセキュリティ対策 まとめ

# はじめに

書籍「 [体系的に学ぶ 安全な Web アプリケーションの作り方](https://www.amazon.co.jp/dp/4797393165) 」では、PHP を使用したサンプルコードを例に挙げて、Web アプリケーションのセキュリティについて解説しています。

この内容を受け、Spring Boot と Spring Security の組み合わせにおけるデフォルトの設定や対策機能についても気になったので調べてみました。この記事はその備忘録です。

主に同書籍の第 4 章で取り上げられている脆弱性を対象とし、公式ドキュメントを中心にまとめました。
OS コマンドインジェクションや安全ではないデシリアライゼーションなど、Spring Framework での対策が見つけられなかった脆弱性に関しては言及していません。

以下の環境で動作確認を行いながら進めました。

- Java 17
- Spring Boot 3.2.3
  - spring-boot-starter-security
  - mybatis-spring-boot-starter
  - spring-boot-starter-thymeleaf
- OWASP ZAP 2.12.0

誤りなどがありましたら、お知らせいただけますと幸いです。

# XSS

## 一般的な対策

- コンテキストに応じた特殊文字や制御文字のエスケープを行う
- Cookie に `HttpOnly` 属性を付与する
- ユーザ向けに詳細なエラーメッセージを表示しない
- `Content-Type` ヘッダを正しく設定する
- `X-Content-Type-Options: nosniff` ヘッダを設定する
- CSP を使用して、許可されたソースからのみスクリプトやリソースを読み込む

## Spring Framework の対策

### HTTP レスポンスヘッダ

Spring Security のデフォルト設定では、`OWASP` の推奨事項に従い、`X-XSS-Protection` ヘッダに 0 が設定されています。
また、コンテンツの `MIME` タイプをスニッフィングさせないために、`X-Content-Type-Options: nosniff` ヘッダもデフォルトで追加されています。

しかし、コンテキストに応じた設定が必要な `Content Security Policy (CSP)` ヘッダは、デフォルトでは追加されていないため、必要に応じて設定しなければなりません。

以下は CSP ヘッダを設定する例です。

```java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			// ...
			.headers(headers -> headers
				.contentSecurityPolicy(csp -> csp
					.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
				)
			);
		return http.build();
	}
}
```

セッション Cookie に関しては、Spring Security では直接制御しないため、サーブレットコンテナで設定を行う必要があります。

ただし、Spring Boot を使用し、組み込みのサーブレットコンテナを使用している場合は、`server.servlet.session.cookie.*` プロパティを使用して変更することができます。

**参考**

- [X-XSS-Protection | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/features/exploits/headers.html#headers-xss-protection)
- [コンテンツ型オプション | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/features/exploits/headers.html#headers-content-type-options)
- [コンテンツセキュリティポリシー (CSP) | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/exploits/headers.html#servlet-headers-csp)
- [Java 構成 :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/configuration/java.html)
- [server.servlet.session.cookie.http-only | Spring Boot アプリケーションプロパティ設定一覧 - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server.server.servlet.session.cookie.http-only)
- [Secure Session Cookie | Control the Session with Spring Security - Baeldung](https://www.baeldung.com/spring-security-session#secure-session-cookie)

## Thymeleaf の対策

### HTML エスケープ

Thymeleaf では基本的な XSS 対策が施されているため、適切に使用すれば安全です。

ただし、`th:utext` や `[(...)]` など、値を HTML エスケープせずに出力する機能もあります。これらを使用してユーザからの入力値を出力する場合は、十分な検証やエスケープ処理を行うことが重要です。

**参考**

- [More on texts and variables | Using Thymeleaf](https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#more-on-texts-and-variables)
- [inline | Using Thymeleaf](https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#inlining)

# SQL インジェクション

## 一般的な対策

- プレースホルダを使用して SQL を組み立てる
- データベースには最小限の権限を付与する
- ユーザ向けに詳細なエラーメッセージを表示しない

## MyBatis の対策

### プレースホルダ

MyBatis では、SQL 文の中に変数を埋め込む際に `#{...}` を使用することが推奨されています。この方法を使用すると、MyBatis が内部で `PreparedStatement` を使用して安全に値を埋め込むため、SQL インジェクション攻撃から保護されます。

しかし、`ORDER BY` 句のように、動的に列名のようなメタ情報を埋め込みたい場合もあります。そのようなときは、代わりに `${...}` を使用できますが、この方法ではエスケープが行われません。
そのため、ユーザからの入力値を使用したい場合は、適切な検証やエスケープ処理を行うことで、安全性を確保することが重要です。

**参考**

- [mybatis – MyBatis 3 | Mapper XML ファイル](https://mybatis.org/mybatis-3/ja/sqlmap-xml.html#parameters)

# CSRF

## 一般的な対策

- 秘密情報 (CSRF トークン) を埋め込む
- `Referer` を確認する
- Cookie に `SameSite` 属性を付与する
- 変更を伴うリクエストに `GET`、`HEAD`、`OPTIONS`、`TRACE` メソッドを使用しない
- 重要な操作には二段階認証を使用する

## Spring Framework の対策

### HTTP レスポンスヘッダ

組み込みのサーブレットコンテナを使用する Spring Boot では、`server.servlet.session.cookie.same-site` プロパティでセッション Cookie の `SameSite` 属性を変更できます。

そのほかの Cookie の `SameSite` 属性を変更したい場合は、以下のように `CookieSameSiteSupplier` を使って設定します。

```java
@Configuration(proxyBeanMethods = false)
public class MySameSiteConfiguration {

    @Bean
    public CookieSameSiteSupplier applicationCookieSameSiteSupplier() {
        return CookieSameSiteSupplier.ofLax().whenHasNameMatching("myapp.*");
    }
}
```

**参考**

- [SameSite クッキー | Spring Boot Web - リファレンスドキュメント (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/web.html#web.servlet.embedded-container.customizing.samesite)
- [SameSite 属性 | クロスサイトリクエストフォージェリ（CSRF）: : Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/features/exploits/csrf.html#csrf-protection-ssa)
- [埋め込みサーブレットコンテナーのカスタマイズ | Spring Boot Web - リファレンスドキュメント (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/web.html#web.servlet.embedded-container.customizing)
- [server.servlet.session.cookie.same-site | Spring Boot アプリケーションプロパティ設定一覧 - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server.server.servlet.session.cookie.same-site)

### CSRF トークン

Spring Security では、デフォルトで CSRF 対策機能が有効になっています。

CSRF トークンは、安全でランダムな値として自動生成され、フォームの hidden フィールドや HTTP ヘッダに埋め込まれます。
リクエストを送信する際には、このトークンも一緒に送信するため、サーバ側では、受信したトークンと期待される値を比較することで、リクエストが正当なものであるかを確認します。
これにより、CSRF 攻撃からアプリケーションを保護することができます。

なお、デフォルトでは `POST`、 `PUT`、 `DELETE`、 `PATCH` メソッドを使用した HTTP リクエストに対してのみ CSRF トークンチェックが行われます。

**参考**

- [シンクロナイザートークンパターン | クロスサイトリクエストフォージェリ（CSRF）:: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/features/exploits/csrf.html#csrf-protection-stp)
- [CSRF 保護との統合 | クロスサイトリクエストフォージェリ（CSRF）: : Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/exploits/csrf.html#csrf-integration)

# クリックジャッキング

## 一般的な対策

- `X-Frame-Options` ヘッダを使用して、外部からのフレーム埋め込みを制御する

## Spring Framework の対策

### HTTP レスポンスヘッダ

Spring Security のデフォルトでは、`X-Frame-Options: DENY` ヘッダを設定して、`iframe` 内のページのレンダリングを無効にしています。

**参考**

- [X-Frame-Options | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/features/exploits/headers.html#headers-frame-options)

# セッションハイジャック

## 一般的な対策

- 推測が困難なセッション ID を生成する
- セッション ID は Cookie を使って連携する
- Cookie に `HttpOnly` 属性を付与する
- Cookie に `Secure` 属性を付与する
- `HTTPS` を使って通信を暗号化する

## Spring Framework の対策

### セッション ID の生成と管理

セッション ID の生成と管理はサーブレットコンテナが行うため、開発者が直接操作する必要はありません。

セッション ID の生成方法はサーブレットコンテナごとに異なります。
たとえば `Tomcat` のデフォルトでは 16 進数表記された 32 文字のランダムな文字列として生成し、`JSESSIONID` という名前の Cookie に格納します。

**参考**

- [認証の永続性とセッション管理 ::Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/authentication/session-management.html)
- [Apache Tomcat 9 Configuration Reference (9.0.86) - The SessionIdGenerator Component](https://tomcat.apache.org/tomcat-9.0-doc/config/sessionidgenerator.html)

### URL Rewriting

`URL Rewriting` とは、Cookie を使用できないクライアントとセッションを維持するための仕組みのことで、サーブレットコンテナによって提供されます。

この仕組みでは、URL のリクエストパラメータを使ってサーバとクライアントの間でセッション ID を共有します。
たとえば、`http://localhost:8080/;jsessionid=3ACB490E688E2C3BC729B277EC3D6A7D` の場合、`jsessionid=3ACB490E688E2C3BC729B277EC3D6A7D` の部分が URL Rewriting されたセッション ID です。

しかし、この `URL Rewriting` は、セッション ID を漏洩させる危険性を高いため、無効化することが望ましいとされています。
Spring Security においても、デフォルトでセミコロンを含む URL を無効なリクエストとして判断するため、`URL Rewriting` によるセッション ID の連携は行えません。

**参考**

- [HttpFirewall :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/exploits/firewall.html)
- [StrictHttpFirewall (spring-security-docs API) - Javadoc (pleiades.io)](https://spring.pleiades.io/spring-security/site/docs/current/api/org/springframework/security/web/firewall/StrictHttpFirewall.html)
- [Prevent Using URL Parameters for Session Tracking | Control the Session with Spring Security - Baeldung](https://www.baeldung.com/spring-security-session#no-url-params)
- [Session Management - OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#session-management-implementation)

# セッション固定攻撃

## 一般的な対策

- セッション ID は `Cookie` を使って連携する
- 認証後にセッション ID を変更する

## Spring Framework の対策

### 認証後のセッション ID 変更

Spring Security では、デフォルトでユーザがログインするときにセッション ID を変更する仕組みが有効になっています。

**参考**

- [セッション固定攻撃保護について | 認証の永続性とセッション管理 ::Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/authentication/session-management.html#ns-session-fixation)
- [ChangeSessionIdAuthenticationStrategy (spring-security-docs API) - Javadoc (pleiades.io)](https://spring.pleiades.io/spring-security/site/docs/current/api/org/springframework/security/web/authentication/session/ChangeSessionIdAuthenticationStrategy.html)

# HTTP ヘッダインジェクション

## 一般的な対策

- 外部からの入力値を直接 HTTP ヘッダとして出力しない
- HTTP ヘッダの出力部分は言語やライブラリが提供するヘッダ出力用 API を使用する
- HTTP ヘッダに含まれる特殊文字や制御文字をエスケープする

## Spring Framework の対策

### HTTP ヘッダのバリデーション

Servlet API では、`HttpServletResponseWrapper` クラスを使用してレスポンスをカスタマイズできます。

Spring Security のデフォルトでは、このクラスを拡張した `FirewalledResponse` というクラスを適用して、HTTP ヘッダの検証を行っています。
具体的には、レスポンスヘッダに値を設定するときに、入力値に改行文字が含まれていないかを検証し、含まれていた場合は `IllegalArgumentException` を発生させます。

この仕組みにより、改行文字を含む不正なヘッダ値が設定されることを防ぎ、セキュリティを向上させることができます。

**参考**

- [HttpServletResponseWrapper (Jakarta EE Platform API) - Javadoc (pleiades.io)](https://spring.pleiades.io/specifications/platform/10/apidocs/jakarta/servlet/http/httpservletresponsewrapper)

# メールヘッダインジェクション

## 一般的な対策

- 外部からの入力値を直接メールヘッダとして出力しない
- メールの作成や送信には、専用のライブラリを使用する
- メールヘッダに含まれる特殊文字や制御文字はエスケープする

## Spring Framework の対策

### 特殊文字のエスケープ

Spring Framework では、メール送信に関する詳細なロジックを隠蔽し、低レベルの API ハンドリングを代行するためのユーティリティライブラリが提供されています。

これらのライブラリは、内部で `MimeMessage` クラスを使用しており、このクラスでは非 ASCII 文字や特殊文字を含むテキストをメールセーフ形式にエンコードします。これにより、メールの安全性や信頼性が確保されます。

**参考**

- [メール :: Spring Framework - リファレンスドキュメント (pleiades.io)](https://spring.pleiades.io/spring-framework/reference/integration/email.html)
- [MimeMessage (Jakarta EE Platform API) - Javadoc (pleiades.io)](https://spring.pleiades.io/specifications/platform/10/apidocs/jakarta/mail/internet/mimemessage)

# ディレクトリトラバーサル

## 一般的な対策

- ファイルパスを指定するときは、外部からの入力値を使用しない
- ファイルパスを外部から受け取る場合は、特殊文字や制御文字はエスケープする
- アクセス権を適切に管理し、ユーザがアクセス可能なディレクトリやファイルを制限する

## Spring Framework の対策

### 正規化されていないリクエスト

Spring Security では、`HttpServletRequest` と `HttpServletResponse` に対してファイアウォール機能を組み込むために `HttpFirewall` インタフェースが提供されています。

このインタフェースにはいくつかの実装クラスが用意されていますが、Spring Security のデフォルトでは `StrictHttpFirewall` クラスが使用されています。
このクラスは、パストラバーサルシーケンス (`/../` など) を含むような正規化されていないリクエストを拒否するなど、厳格な検証を行います。

**参考**

- [HttpFirewall :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/exploits/firewall.html)
- [StrictHttpFirewall (spring-security-docs API) - Javadoc (pleiades.io)](https://spring.pleiades.io/spring-security/site/docs/current/api/org/springframework/security/web/firewall/StrictHttpFirewall.html)
- [CVE-2018-1199: Security bypass with static resources (spring.io)](https://spring.io/security/cve-2018-1199)

# 意図しないファイル公開

## 一般的な対策

- Web サーバ上の非公開ディレクトリを使用する
- ディレクトリリスティングを無効にする

## Spring Framework の対策

Spring Boot では、ディレクトリリスティングが無効になっているようですが、明確な情報を見つけられませんでした。
調べる過程で参考にしたサイトを記します。

- [デフォルトのサーブレット :: Spring Framework - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-framework/reference/web/webmvc/mvc-config/default-servlet-handler.html)
- [静的コンテンツ :: Spring Boot Web - リファレンスドキュメント (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/web.html#web.servlet.spring-mvc.static-content)
- [静的リソース :: Spring Framework - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-framework/reference/web/webmvc/mvc-config/static-resources.html)
- [Apache Tomcat 9 (9.0.87) - Default Servlet Reference](https://tomcat.apache.org/tomcat-9.0-doc/default-servlet.html)

# ファイルアップロード機能に対する DoS 攻撃

## 一般的な対策

- ファイル当たりのサイズ制限を設ける
- リクエストのボディサイズ制限を設ける

## Spring Framework の対策

### サイズ制限

Spring Boot では `spring.servlet.multipart.*` プロパティを使用して、ファイルアップロードに関する設定を行うことができます。

DoS 攻撃対策としては、`max-file-size` でアップロードを許可する 1 ファイルあたりの最大バイト数を指定し、`max-request-size` で `multipart/form-data` リクエストの `Content-Length` の最大値を指定します。

これらの値を超えた場合は、`org.springframework.web.multipart.MaxUploadSizeExceededException` が発生します。

| 名前                                                 | 説明                                         | デフォルト値 |
|----------------------------------------------------|--------------------------------------------|--------|
| spring.servlet.multipart.enabled                   | マルチパートアップロードのサポートを有効にするかどうか                | true   |
| spring.servlet.multipart.file-size-threshold       | ファイルがディスクに書き込まれるまでのしきい値                    | 0B     |
| spring.servlet.multipart.location                  | アップロードされたファイルの中間場所                         |        |
| spring.servlet.multipart.max-file-size             | 最大ファイルサイズ                                  | 1MB    |
| spring.servlet.multipart.max-request-size          | 最大リクエストサイズ                                 | 0MB    |
| spring.servlet.multipart.resolve-lazily            | ファイルまたはパラメーターのアクセス時にマルチパートリクエストを遅延解決するかどうか | false  |
| spring.servlet.multipart.strict-servlet-compliance | サーブレット仕様に厳密に従ってマルチパートリクエストを解決するかどうか        | false  |

**参考**

- [入門 | ファイルのアップロード (pleiades.io)](https://spring.pleiades.io/guides/gs/uploading-files)
- [マルチパート :: Spring Framework - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/multipart-forms.html)
- [spring.servlet.multipart.enabled | Spring Boot アプリケーションプロパティ設定一覧 - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.web.spring.servlet.multipart.enabled)
- [MultipartFile (Spring Framework API) - Javadoc (pleiades.io)](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html)

# ファイルインクルード攻撃

## 一般的な対策

- 外部からの入力値をインクルードするファイルパスに使用しない
- ファイルパスを外部から受け取る場合は、特殊文字や制御文字はエスケープする
- 外部ファイルの参照を無効にする

## Thymeleaf の対策

### テンプレートのインクルード

Thymeleaf では `th:insert` や `th:replace` を使用して、テンプレート内の一部を別のテンプレートからインクルードすることができます。

さらに、`UrlTemplateResolver` を使用してテンプレートエンジンを構成することで、外部サーバ上にあるテンプレートをインクルードすることも可能になるようです。

これらを使用する際に、テンプレート名やフラグメント名としてユーザが入力した値を使用するならば、適切な検証を行って対策を行わなければなりません。

※ th:include は、Thymeleaf 3.1 で非推奨化されました。

**参考**

- [Fragment specification syntax | Thymeleaf Page Layouts - Thymeleaf](https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#fragment-specification-syntax)
- [Including with Markup Selectors | Thymeleaf Page Layouts - Thymeleaf](https://www.thymeleaf.org/doc/articles/layouts.html#including-with-markup-selectors)
- [Template Resolvers | Tutorial: Using Thymeleaf](https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#template-resolvers)
- [Rendering Template Fragments | Tutorial: Thymeleaf + Spring](https://www.thymeleaf.org/doc/tutorials/3.1/thymeleafspring.html#rendering-template-fragments)
- [Thymeleaf 3.1: What’s new and how to migrate - Thymeleaf](https://www.thymeleaf.org/doc/articles/thymeleaf31whatsnew.html#deprecation-of-thinclude)

# キャッシュからの情報漏洩

## 一般的な対策

- 認証が必要な情報やユーザ毎に表示内容が異なる個人情報をキャッシュしない
- キャッシュサーバやレスポンスヘッダの設定を適切に行う

## Spring Framework の対策

### HTTP レスポンスヘッダ

Spring Security のデフォルトでは、ユーザのコンテンツを保護するためにキャッシュが無効となっています。

デフォルトのキャッシュ制御 HTTP レスポンスヘッダは以下のとおりです。

```
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
```

特定のレスポンスをキャッシュしたい場合は、`HttpServletResponse.setHeader()` メソッドを使ってこれらの値をオーバーライドします。

また、デフォルトでは有効になっていませんが、ログアウトするときに `Clear-Site-Data` ヘッダを送信する設定も簡単に行うことができます。

```java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			// ...
			.logout((logout) -> logout
                .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)))
			);
		return http.build();
	}
}
```

**参考**

- [キャッシュ制御 | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/features/exploits/headers.html#headers-cache-control)
- [サーブレット キャッシュ制御 | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/exploits/headers.html#servlet-headers-cache-control)
- [サイトデータのクリア | セキュリティ HTTP レスポンスヘッダー :: Spring Security - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-security/reference/servlet/exploits/headers.html#servlet-headers-clear-site-data)

# JSON エスケープの不備

## 一般的な対策

- 信頼できるライブラリを用いて JSON を生成する

## Spring Framework の対策

### JSON レスポンスの生成

Spring MVC では、`@ResponseBody` アノテーションが付与されたコントローラメソッドの返り値は、`HttpMessageConverter` によってクライアントが要求したメディアタイプに自動的に変換されます。

とくに、Spring Boot の場合は、デフォルトで `Jackson` ライブラリが含まれており、JSON 形式のレスポンスを処理する `MappingJackson2HttpMessageConverter` が有効になっています。

そのため、`Accept` ヘッダに `application/json` が指定されたリクエストを受け取ると、自動的に `MappingJackson2HttpMessageConverter` が選択され、コントローラメソッドの戻り値は `Jackson` によって JSON 形式に変換されてからレスポンスボディに書き込まれます。

`Jackson` は、JSON 文字列を安全に表現するためにバックスラッシュやダブルクォートをエスケープしますが、HTML エスケープなどは行いません。そのため、それらが必要な場合はカスタマイズを行う必要があります。

- [Spring Boot REST API の作成 - 公式サンプルコード (pleiades.io)](https://spring.pleiades.io/guides/gs/rest-service)
- [Http Message Converters with the Spring Framework | Baeldung](https://www.baeldung.com/spring-httpmessageconverter-rest)

# 文字エンコーディングの不備

## Spring Framework の対策

### 文字エンコードの強制

組み込みのサーブレットコンテナを使用する Spring Boot では、`server.servlet.encoding.*` プロパティを使用して、リクエストおよびレスポンス処理のための文字エンコード動作を変更できます。

具体的には、`server.servlet.encoding.enabled` を `true` に設定すると、HTTP エンコーディングサポートが有効になり、リクエストごとに `CharacterEncodingFilter.doFilterInternal()` メソッドが呼び出されます。
このメソッドでは `force-request` が true の場合、リクエストの文字エンコーディングを `charset` で指定された文字エンコーディングに強制的に上書きします。

| 名前                                     | 説明                                           | デフォルト値                          |
|----------------------------------------|----------------------------------------------|---------------------------------|
| server.servlet.encoding.charset        | HTTP リクエストおよびレスポンスの文字セット                     | UTF-8                           |
| server.servlet.encoding.enabled        | HTTP エンコーディングサポートを有効にするかどうか                  | true                            |
| server.servlet.encoding.force          | HTTP リクエストおよびレスポンスで設定された文字セットにエンコードを強制するかどうか |                                 |
| server.servlet.encoding.force-request  | HTTP リクエストで構成された文字セットにエンコードを強制するかどうか         | force に従うが、force が未指定の場合は true  |
| server.servlet.encoding.force-response | HTTP レスポンスで構成された文字セットにエンコードを強制するかどうか         | force に従うが、force が未指定の場合は false |
| server.tomcat.uri-encoding             | URI のデコードに使用する文字エンコード                        | UTF-8                           |

※ Spring Boot 2.0.3 において spring.http.encoding.* から server.servlet.encoding.* に変更されました。

**参考**

- [文字エンコード | Spring Boot Web - リファレンスドキュメント (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/web.html#web.servlet.embedded-container.customizing.encoding)
- [server.servlet.encoding.charset | Spring Boot アプリケーションプロパティ設定一覧 - リファレンス (pleiades.io)](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server.server.servlet.encoding.charset)
- [CharacterEncodingFilter (Spring Framework API) - Javadoc (pleiades.io)](https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/CharacterEncodingFilter.html)
- [Spring Boot 2.3.0 Configuration Changelog](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3.0-Configuration-Changelog)