Spring Bootでの入力検証ガイド
Lucien Chemaly
2023年9月12日
0 分で読めますJavaを使う開発者なら、スタンドアロンの本番環境対応Springベースアプリケーションの開発を効率化する堅牢なフレームワーク、Spring Bootをご存じでしょう。その多くの機能の1つが、データの整合性を確保し、ユーザー体験を向上させるうえで重要なBean Validationです。
Spring Bootアプリケーションでは、入力やフォームの検証、データベースへの保存前のデータ検証、さまざまなセキュリティポリシーの適用にBean Validationを利用できます。Bean Validationを使うことで、開発者はエラーを防ぎ、アプリケーション全体の品質を高め、アプリケーション全体でデータの一貫性を保てます。
この記事では、Bean Validationのさまざまな用途と、Spring Bootでの実装方法について解説します。自分のプロジェクトで効果的に活用する方法を学びましょう。
Bean Validationとは
Bean Validationは、アプリケーションのデータモデルに制約を適用し、データが処理または保存される前に特定のルールに準拠していることを確認できる機能です。これは、制約の定義と検証に使用するアノテーションとインターフェースを提供するJakarta Bean Validationとの統合によって実現されます。
Bean Validationを適用すると、開発プロセスの早い段階でエラーや不整合を検出できるため、開発者は時間とリソースを節約できます。また、誤ったデータが入力されるのを減らし、ユーザー体験全体の向上にも役立ちます。
アプリケーション開発におけるBean Validationの一般的な用途をいくつか見てみましょう。
入力とフォームの検証
Bean Validationの最も一般的な用途の1つは、入力やフォームの検証です。これにより、ユーザーが正しい形式でデータを入力していることを確認できます(例:メールアドレス、ユーザー名、パスワードを使う登録フォームの検証)。
データベースへの保存前のデータ検証
Bean Validationは、データベースに保存する前のデータ検証にも利用できます。この手法により、入力されたデータの一貫性と正確性を確保できます。その結果、エラーを防ぎ、データ破損のリスクを軽減できます。
セキュリティポリシーの適用
Bean Validationは、ユーザー入力やデータベースからマッピングされたデータを検証し、パスワード強度の要件など、特定の基準を満たしていることを確認することで、セキュリティポリシーの適用にも利用できます。検証はインジェクション攻撃の防止に重要な役割を果たし、保存型クロスサイトスクリプティング(XSS)などのセキュリティ脆弱性の防止にも役立ちます。
ビジネスロジックの検証
Bean Validationを使ってビジネスロジックを検証し、特定の要件や標準を満たしていることを確認できます。パスワードの複雑さや、注文品目の数量・価格の妥当性などの制約を定義すると、Bean Validationがデータを自動的にチェックし、必要なルールを適用します。これにより手作業での確認をなくし、アプリケーションが特定の標準や要件に準拠していることを確保できます。
Spring BootでBean Validationを実装する
このチュートリアルでは、インメモリデータベースを使ったシンプルな作成・読み取り・更新・削除(CRUD)アプリケーションにBean Validationを実装します。ユーザーが名前、メールアドレス、パスワードを入力し、特定の条件を満たした場合に受け付けます。ここでは、RESTful APIを備えたバックエンドサーバーとインメモリH2データベースで構成される、次の高レベルアーキテクチャを使用します。
クライアントアプリケーションがWebサービス(このチュートリアルで作成するアプリケーション)を呼び出すと、リクエストはUserController.に届きます。次に、コントローラーがリクエストデータを検証します。データが有効であれば、リクエストはUserRepositoryに渡され、インメモリデータベースと通信して該当する応答を返します。無効な場合は、エラーメッセージとともにリクエストがクライアントに返されます。

前提条件
実装を始める前に、次のツールとテクノロジーがインストールされていることを確認してください。
IntelliJ IDEAやEclipseなどのIDE。このチュートリアルではIntelliJ IDEA Community Editionを使用します。
Maven 3.8.6以上。
新しいSpring Bootプロジェクトを作成する
新しいSpring Bootプロジェクトを作成するには、Spring Initializrにアクセスし、次のオプションを選択します。
プロジェクトの種類: Maven Project
言語: Java
パッケージ形式: Jar
Javaのバージョン: 17
Spring Boot: 3.1.0 (SNAPSHOT)
Project Metadataセクションに次の詳細を入力します。
Group: com.example
Artifact: simple-crud-bean-validation
Name: simple-crud-bean-validation
Description: Spring Bootを使ったシンプルなCRUDアプリケーション
Package name: com.example.simplecrud
次の依存関係も追加します。
Web: Spring Web
Validation: Bean Validation
H2 Database: H2 Database
Spring Data JPA: Spring Data and Hibernate

Generateをクリックして、プロジェクトをZIPファイルとしてダウンロードします。ZIPファイルを展開し、お好みのIDEにプロジェクトをインポートします。
アプリケーションを実装する
Spring Bootアプリケーションの標準的なプロジェクト構成に従います。プロジェクト全体の構成は次のとおりです。

Userモデル
アプリケーションを実装するには、まずsrc/main/java/com/example/simplecrudbeanvalidation内にmodelディレクトリを作成します。次に、modelディレクトリ内にUser.javaというファイルを作成し、次のフィールドとBean ValidationアノテーションをUserクラスに追加します。
このコードは、Jakarta Persistence API(JPA)のアノテーションを使い、データベース内のusersテーブルを表すUserというJavaクラスを定義します。インスタンス変数はid、name、email、passwordの4つで、それぞれに対応するgetterとsetterがあります。各フィールドには、@NotNull、@NotEmpty、@Email、@Size、@Patternなどの検証制約が設定されています。@Patternは、パスワードが8~64文字で、数字、小文字、大文字、特殊文字をそれぞれ少なくとも1つ含む必要があることを指定します。また、@Patternはnameプロパティにも使われ、スクリプトインジェクションを防ぎます。このクラスは、データベースにユーザーデータを保存したり、取得したりするためのモデルクラスとして使用できます。
Userリポジトリ
インメモリデータベースでCRUD操作を処理するには、src/main/java/com/example/simplecrudbeanvalidation内にrepositoryディレクトリを作成します。次に、repositoryのdirectory内にUserRepository.javaというファイルを作成し、次のようにUserRepositoryインターフェースを定義します。
このコードは、Spring Data JPAが提供するCrudRepositoryインターフェースを拡張する、UserRepositoryというJavaインターフェースを定義します。UserRepositoryインターフェースでは、CrudRepositoryに2つの型パラメーターを指定します。1つはこのリポジトリが管理するエンティティ型のUser、もう1つはエンティティの主キー型のLongです。
CrudRepositoryを拡張することで、UserRepositoryはUserエンティティに対するCRUD操作用の複数のメソッドを継承します。これらのメソッドを使うと、複雑な設定や本格的なデータベースサーバーを用意せずに、インメモリデータベースと連携してUserオブジェクトを管理できます。
Userコントローラー
RESTful APIのエンドポイントと検証ロジックを定義するUserControllerクラスを作成するには、まずsrc/main/java/com/example/simplecrudbeanvalidationディレクトリ内にcontrollerというディレクトリを作成します。次にcontrollerディレクトリ内にUserController.javaというファイルを作成し、次の内容を記述します。
このコードは、UserControllerというSpring BootのRestControllerクラスを定義し、Userオブジェクトを管理するHTTPリクエストを処理します。このクラスには、すべてのユーザーの取得、IDによる単一ユーザーの取得、新規ユーザーの作成、既存ユーザーの更新、ユーザーの削除という5種類のHTTPリクエストを処理するメソッドがあります。
@Autowiredアノテーションは、UserRepositoryの依存関係をUserControllerクラスに注入するために使われます。UserControllerクラスは@RequestMappingアノテーションによって/api/usersエンドポイントに関連付けられ、受信したHTTPリクエストがこのコントローラーに割り当てられます。また、@Validatedアノテーションを使うと、リクエストパラメーターの検証が有効になります。このコードは全体として、Spring Dataとインメモリデータベースを使い、Userオブジェクトに対するCRUD操作を行うRESTful APIを提供します。
インメモリデータベースを設定する
インメモリデータベースを設定するには、src/main/resources/内のapplication.propertiesを開き、次の設定を追加します。
このSpring Bootの設定では、testdbという名前のH2インメモリデータベースをセットアップし、ドライバー、ユーザー名、パスワードを設定します。また、Hibernateベースのデータベース操作で使用するH2の方言も指定します。
本番環境でのH2の使用は推奨されません
本番データベースとしてH2を使用することは推奨されません。また、本番環境ではデフォルトのユーザー名とパスワードを使用しないでください。この設定はデモ用途には適していますが、本番環境では使用しないでください。
Bean Validationの単体テスト
インメモリデータベースの設定が完了したら、Bean Validationの単体テストを始められます。src/test/java/com/example/simplecrudbeanvalidation内にcontrollerディレクトリを作成します。次にcontrollerディレクトリ内にUserControllerTest.javaというファイルを作成し、Bean Validationの制約が想定どおりに機能することを確認するテストを記述します。
UserControllerTestクラスに次のコードを追加します。
このコードはUserControllerクラスに対するJUnitテストのセットです。テストではMockMvcクラスを使って/api/usersエンドポイントへのHTTPリクエストをシミュレートし、UserControllerクラス内の対応するメソッドが正しく処理することを確認します。テストでは、有効なデータと無効なデータを使った新規ユーザーの作成、すべてのユーザーの取得、ユーザーが存在する場合と存在しない場合のIDによるユーザー取得などを検証します。
@SpringBootTestアノテーションはアプリケーションコンテキストの読み込みに使われ、@MockBeanアノテーションはUserControllerクラスの依存関係であるUserRepositoryをモック化するために使われます。これらのテストにより、UserControllerクラスが正しく機能し、さまざまなHTTPリクエストに適切に応答することを確認できます。
テストを実行するには、ターミナルまたはシェルを開き、プロジェクトのルートディレクトリに移動して、次のコマンドを実行します。
すべてのテストが成功したことを確認できます。
APIを実行してテストする
IntelliJでSimpleCrudBeanValidationApplication.javaファイルを右クリックし、Run 'SimpleCrudBeanValidationApplication.main()'を選択します。

または、次のコマンドを使ってターミナルやシェルからアプリケーションを実行することもできます。
Spring Bootアプリケーションを起動したら、ターミナルやシェルからcurlコマンドを使ってCRUD操作をテストできます。これは、フロントエンドアプリケーションやPostmanからこれらのAPIを呼び出す方法と同様です。
CRUD操作をテストするには、まずユーザーを作成します。
次のように出力されます。
次に、すべてのユーザーを取得します。
次のように出力されます。
次に、IDを指定してユーザーを取得します。取得したいユーザーのIDを<id>に置き換えてください。
出力は次のとおりです。
ユーザーを更新するには、更新したいユーザーのIDを<id>に置き換えます。
次のように出力されます。
次に、削除したいユーザーのIDを<id>に置き換えて、ユーザーを削除します。
このコマンドの出力は空です。
これらのcurlコマンドを使って、User RESTful APIのCRUD操作をテストできます。各コマンドの<id>は、適切なユーザーIDに置き換えてください。以下の手順に沿ってSpring Bootアプリケーションを操作し、実行時にBean Validationの制約が想定どおりに機能することを確認できます。
無効なメールアドレスやパスワード、空の値など、不正なデータを使ってこれらのcurlリクエストを再度実行すると、APIから不正なリクエストのエラーが返されます。このエラーメッセージは、コントローラーレベルで行われる検証(Bean Validationとも呼ばれます)が失敗したことを示しています。
不正なリクエストの例を見てみましょう。ここでは、無効なメールアドレスでユーザーを作成します。
出力は次のようになります。
次に、無効なパスワードでユーザーを作成します。
出力は次のとおりです。
Bean Validationのまとめ
この記事では、シンプルなCRUDアプリケーションにSpring BootのBean Validationを実装する方法を学びました。Spring Initializrを使ってプロジェクトを作成し、必要な依存関係を追加したうえで、Bean Validationのアノテーションを使ったユーザーモデルを実装しました。また、UserRepositoryと、Bean Validationを利用するRESTful APIエンドポイントを備えたUserControllerを実装し、Bean Validationの制約が想定どおりに機能することを確認するテストを作成しました。
アプリケーションのセキュリティをさらに強化するには、インジェクション攻撃につながる安全でないコードパターンを検出するSASTのSnyk Codeを活用しましょう。IntelliJ IDE向けSnyk Securityプラグイン拡張機能を使うと、この分析を開発ワークフローに組み込めます。
Spring BootのBean Validationの仕組みを理解したら、自分のプロジェクトにも実装して、データの整合性を確保し、ユーザーエクスペリエンスを向上させましょう。完成したコードは、こちらのGitHubリポジトリでご確認ください。
Capture the Flagを始めよう
オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。
