きり丸の技術日記

技術・エンジニアのイベント・資格等はこちらにまとめる予定です

【SpringBoot】画面項目をサーバでバリデーションする

きり丸アドベントカレンダー2020の12記事目です。


画面の項目が必須項目なのか、数字のみ許容するのか、Email形式のみしか許容しないのかをサーバ側で検証する必要があります。この項目を検証することをバリデーションと言います。

基本的には画面側のJavaScriptでも検証すべきですが、javaScriptは開発者モードで無効化することもできたりするので、最終的にはサーバ側で検証したほうがいいです。

ゴール

  • 画面項目をサーバでバリデーションする

f:id:nainaistar:20201129171857p:plain f:id:nainaistar:20201129171912p:plain

環境

  • Java
    • 15
  • org.springframework.boot:spring-boot-starter-validation
    • 2.4.0

手順

バリデーション用ライブラリをインストール


2.3より前のバージョンは、spring-boot-starter-webにバリデーション用ライブラリが含まれていましたが、2.3以降からライブラリが分かれてしまったため、spring-boot-starter-validationを含める必要があります。

おそらく、最近SpringBootを最新にしている人はちょっとだけ引っかかるポイントです。

ファイル名:build.gradle

   implementation 'org.springframework.boot:spring-boot-starter-validation'

DTOに制約を付与する


下記項目のidに関しては、空文字からintに変換できないので、一応そのままでも大丈夫です。IDは1~1000までしか採番したくない、という場合は@Min(1)@Max(1000)を付与します。

今回の場合、他の項目が空文字だとデータとして意味が無いので、空文字を許容しない@NotNullを付与します。

ファイル名:TodoDto.java

public class TodoDto {
    @Min(1) @Max(1000)
    @NotNull
    int id;
    @NotNull
    String userId;
    @NotNull
    String action;
}

他にも色んなバリデーションをかけられます。次のJavadocから詳細を確認してみてください。

https://spring.pleiades.io/specifications/platform/8/apidocs/


SpringBoot自体には含まれてませんが、Hibernateを使用している場合の@CreditCardNumber等のバリデーションは面白いですね。

docs.jboss.org

ソースコードにバリデーションすることを明示する


パラメータのTodoDtoクラスに@Validatedを付与すると上記で設定した@NotNullが有効になります。もし、これらのアノテーションを満たしていない場合はBadRequestとして返却されます。

@PostMapping(value="/", params="add")
public String add(@Validated TodoDto model){
    todoRepository.insert(model);
    return "redirect:/";
}

テストコードで確認する


ControllerのAddメソッドが呼ばれたときに、バリデーションを有効にしました。次のテストコードは、アノテーションを満たして正常処理されるパターンと、満たせずにBadRequestとして処理されるパターンを検証しています。

@Test
void test_01() throws Exception {

    TodoDto expected = TodoDto.builder()
        .id(123)
        .userId("user")
        .action("actionする")
        .build();

    mockMvc.perform(MockMvcRequestBuilders.post("/")
        .param("add", "add")
        .param("id", "123")
        .param("userId", "user")
        .param("action", "actionする")
    )
        .andExpect(status().isFound());

    Mockito.verify(todoRepository).insert(expected);
}

@Test
void test_02() throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.post("/")
        .param("add", "add")
    )
        .andExpect(status().is4xxClientError());
}

ソースコード

アドベントカレンダー12日目。
github.com

終わりに

画面で入力されたデータを検証しないと、意図しないデータが含まれてしまい、修正が難しくなります。ですので、事前にバリデーションを多めに行っておくことが大事になります。

データを別システムが持っている場合、厳しすぎるバリデーションが問題になることもありますが…。単純なバリデーションならやっておくべきでしょう。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考記事

敬称略。

リファレンス。 spring.pleiades.io

類似記事

きり丸アドベントカレンダー2020 adventar.org

きり丸のHerokuページ
https://kirimaru-todoapp.herokuapp.com/

13日目のアドベントカレンダーの記事 https://nainaistar.hatenablog.com/entry/2020/12/13/083000nainaistar.hatenablog.com

f:id:nainaistar:20201109133010p:plain