前言
參數驗證很重要,是平時開發環節中不可少的一部分,但是我想很多后端同事會偷懶,干脆不錯,這樣很可能給系統的穩定性和安全性帶來嚴重的危害。那么在Spring Boot應用中如何做好參數校驗工作呢,本文提供了10個小技巧,你知道幾個呢?
1.使用驗證注解
Spring Boot
提供了內置的驗證注解,可以幫助簡單、快速地對輸入字段進行驗證,例如檢查 null 或空字段、強制執行長度限制、使用正則表達式驗證模式以及驗證電子郵件地址。
一些最常用的驗證注釋包括:
@NotNull
:指定字段不能為空。@NotEmpty
:指定列表字段不能為空。@NotBlank
:指定字符串字段不得為空或僅包含空格。@Min
和@Max
:指定數字字段的最小值和最大值。@Pattern
:指定字符串字段必須匹配的正則表達式模式。@Email
:指定字符串字段必須是有效的電子郵件地址。
具體用法參考下面例子:
public class User {
@NotNull
private Long id;
@NotBlank
@Size(min = 2, max = 50)
private String firstName;
@NotBlank
@Size(min = 2, max = 50)
private String lastName;
@Email
private String email;
@NotNull
@Min(18)
@Max(99)
private Integer age;
@NotEmpty
private List
2 使用自定義驗證注解
雖然 Spring Boot 的內置驗證注釋很有用,但它們可能無法涵蓋所有情況。如果有特殊參數驗證的場景,可以使用 Spring 的 JSR 303 驗證框架創建自定義驗證注釋。自定義注解可以讓你的的驗證邏輯更具可重用性和可維護性。
假設我們有一個應用程序,用戶可以在其中創建帖子。每個帖子都應該有一個標題和一個正文,并且標題在所有帖子中應該是唯一的。雖然 Spring Boot 提供了用于檢查字段是否為空的內置驗證注釋,但它沒有提供用于檢查唯一性的內置驗證注釋。在這種情況下,我們可以創建一個自定義驗證注解來處理這種情況。
首先,我們創建自定義約束注解UniqueTitle
:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueTitleValidator.class)
public @interface UniqueTitle {
String message() default "Title must be unique";
Class?[] groups() default {};
Class? extends Payload[] payload() default {};
}
接下來,我們創建一個PostRepository
接口,目的是從數據庫中檢索帖子:
public interface PostRepository extends JpaRepository<Post, Long> {
Post findByTitle(String title);
}
然后我們需要定義驗證器類 UniqueTitleValidator
,如下所示:
@Component
public class UniqueTitleValidator implements ConstraintValidator<UniqueTitle, String> {
@Autowired
private PostRepository postRepository;
@Override
public boolean isValid(String title, ConstraintValidatorContext context) {
if (title == null) {
return true;
}
return Objects.isNull(postRepository.findByTitle(title));
}
}
UniqueTitleValidator
實現了ConstraintValidator
接口,它有兩個泛型類型:第一個是自定義注解UniqueTitle
,第二個是正在驗證的字段類型(在本例中為String
). 我們還自動裝配了PostRepository
類以從數據庫中檢索帖子。
isValid()
方法通過查詢 PostRepository
來檢查 title
是否為 null 或者它是否是唯一的。如果 title
為 null 或唯一,則驗證成功,并返回 true。
定義了自定義驗證注釋和驗證器類后,我們現在可以使用它來驗證 Spring Boot 應用程序中的帖子標題:
public class Post {
@UniqueTitle
private String title;
@NotNull
private String body;
}
我們已將 @UniqueTitle
注釋應用于 Post
類中的 title
變量。驗證此字段時,這將觸發 UniqueTitleValidator
類中定義的驗證邏輯。
3 在服務器端驗證
除了前端或者客戶端做了驗證意外,服務器端驗證輸入是至關重要的。它可以確保在處理或存儲任何惡意或格式錯誤的數據之前將其捕獲,這對于應用程序的安全性和穩定性至關重要。
假設我們有一個允許用戶創建新帳戶的 REST
端點。端點需要一個包含用戶用戶名和密碼的 JSON 請求體。為確保輸入有效,我們可以創建一個 DTO(數據傳輸對象)類并將驗證注釋應用于其字段:
public class UserDTO {
@NotBlank
private String username;
@NotBlank
private String password;
}
我們使用@NotBlank
注解來確保username
和password
字段不為空或 null。
接下來,我們可以創建一個控制器方法來處理 HTTP POST 請求并在創建新用戶之前驗證輸入:
@RestController
@RequestMapping("/users")
@Validated
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity
我們使用 Spring 的@Validated
注解來啟用方法級驗證,我們還將 @Valid
注釋應用于 userDto
參數以觸發驗證過程。
4 提供有意義的錯誤信息
當驗證失敗時,必須提供清晰簡潔的錯誤消息來描述出了什么問題以及如何修復它。
這是一個示例,如果我們有一個允許用戶創建新用戶的 RESTful API
。我們要確保姓名和電子郵件地址字段不為空,年齡在 18 到 99 歲之間,除了這些字段,如果用戶嘗試使用重復的“用戶名”創建帳戶,我們還會提供明確的錯誤消息或“電子郵件”。
為此,我們可以定義一個帶有必要驗證注釋的模型類 User,如下所示:
public class User {
@NotBlank(message = "用戶名不能為空")
private String name;
@NotBlank(message = "Email不能為空")
@Email(message = "無效的Emaild地址")
private String email;
@NotNull(message = "年齡不能為空")
@Min(value = 18, message = "年齡必須大于18")
@Max(value = 99, message = "年齡必須小于99")
private Integer age;
}
- 我們使用 message屬性為每個驗證注釋提供了自定義錯誤消息。
接下來,在我們的 Spring 控制器中,我們可以處理表單提交并使用 @Valid
注釋驗證用戶輸入:
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<String> createUser(@Valid @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
List<String> errorMessages = result.getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
return ResponseEntity.badRequest().body(errorMessages.toString());
}
// save the user to the database using UserService
userService.saveUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body("User created successfully");
}
}
- 我們使用
@Valid
注釋來觸發User
對象的驗證,并使用BindingResult
對象來捕獲任何驗證錯誤。
-
開發
+關注
關注
0文章
366瀏覽量
40811 -
參數
+關注
關注
11文章
1785瀏覽量
32087 -
spring
+關注
關注
0文章
338瀏覽量
14311 -
SpringBoot
+關注
關注
0文章
173瀏覽量
169
發布評論請先 登錄
相關推薦
評論