2020-05-20 中村
Spring Bootでデータのバリデーション(検査)を行う方法をまとめる
@Viewクラス(Webページ)のフォームから送られてくる値や APIを呼び出す際の引数の型や値を検査して,不正なデータが あれば棄却するようにする仕組み. バリデーションがないと,おかしなEntityがDBに保存されたり, 不正なAPI呼び出しを許したりする.これらのことは, セキュリティホールにもつながる.
HTML5ではバリデーション機能が仕様として追加されたため クライアント側(@View)でバリデーションすることも可能だが,APIを直接呼び出す場合などを考えればサーバ側でやるべき.
Spring Bootの責務から考えると, バリデーションはコントローラ層で行うことが望ましい. まさに「水際ではじくべき」という考えに基づく.
build.gradle のdependenciesに下記を追加
//バリデーション用 compile 'org.springframework.boot:spring-boot-starter-validation'
UserForm.java -- フォーム用のBean
@Data public class UserForm { /* ユーザID は 最大16文字.英数字,アンダーバー,ハイフンのみ許す */ @Size(max = 16) @Pattern(regexp = "[0-9a-zA-Z_\\-]+") private String uid; /* 名前,パスワードは Null,空文字(""),空白のみでないことを検証*/ @NotBlank private String name; @NotBlank private String password; /* RFC2822に準拠したEmailアドレスかどうか検証する */ @Email private String email; }
PitCoinService.java -- コントローラ
@RestController @Scope("request") @RequestMapping("/api") @Slf4j public class PitCoinService { : : @PostMapping("/users") public PitCoinResponse createUser(@RequestBody @Validated UserForm userForm) { // ↑ ユーザフォーム(DTO)をSpringの枠組みで検査する. // 検査失敗したらError Handlerで拾う String uid = userForm.getUid(); log.info("Creating account " + uid); User user = um.createUser(userForm); return PitCoinResponse.createSuccessResponse(user, "User " + uid + " created."); } :
PersonForm.java -- フォーム用のBean
@Data public class PersonForm { /* 名前は無記名は許さない */ @NotBlank private String name; /* 誕生日はyyyy-mm-ddの形式 */ @Pattern(regexp = "\\d{4}-\\d{2}-\\d{2}") private String birthday; /* 身長は0以上.整数部3桁,小数部4桁以内 */ @Min(0) @Digits(integer = 3, fraction = 4) private Double height; // 身長 /* 体重は0以上.整数部3桁,小数部4桁以内 */ @Min(0) @Digits(integer = 3, fraction = 4) private Double weight; // 体重 }
PersonController.java -- コントローラ
@RestController @Scope("request") @RequestMapping("/api") public class PersonController { : @PostMapping("/persons") public PersonDto addPerson(@RequestBody @Validated PersonForm form) { Person p = pm.addPerson(form.toEntity()); return PersonDto.build(p); } :