SpringBoot服務(wù)端數(shù)據(jù)校驗(yàn)過程詳解
這篇文章主要介紹了SpringBoot服務(wù)端數(shù)據(jù)校驗(yàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
對于任何一個應(yīng)用而言,客戶端做的數(shù)據(jù)有效性驗(yàn)證都不是安全有效的,而數(shù)據(jù)驗(yàn)證又是一個企業(yè)級項(xiàng)目架構(gòu)上最為基礎(chǔ)的功能模塊,這時候就要求我們在服務(wù)端接收到數(shù)據(jù)的時候也對數(shù)據(jù)的有效性進(jìn)行驗(yàn)證。為什么這么說呢?往往我們在編寫程序的時候都會感覺后臺的驗(yàn)證無關(guān)緊要,畢竟客戶端已經(jīng)做過驗(yàn)證了,后端沒必要在浪費(fèi)資源對數(shù)據(jù)進(jìn)行驗(yàn)證了,但恰恰是這種思維最為容易被別人鉆空子。畢竟只要有點(diǎn)開發(fā)經(jīng)驗(yàn)的都知道,我們完全可以模擬 HTTP 請求到后臺地址,模擬請求過程中發(fā)送一些涉及系統(tǒng)安全的數(shù)據(jù)到后臺,后果可想而知....
驗(yàn)證分兩種:對封裝的Bean進(jìn)行驗(yàn)證 或者 對方法簡單參數(shù)的驗(yàn)證。
說明:SpringBoot 中使用了 Hibernate-validate 校驗(yàn)框架作為支持
一、引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- 這兩個springboot包里面都包含hibernate-validator包,只要引入一個即可 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
二、hibernate-validator常用注解
- @Valid:被注釋的元素是一個對象,需要檢查此對象的所有字段值
- @Validated :是@Valid 的一次封裝,是Spring提供的校驗(yàn)機(jī)制使用。@Valid不提供分組功能@Null 被注釋的元素必須為 null
- @NotNull:被注釋的元素必須不為 null
- @Pattern(value) :被注釋的元素必須符合指定的正則表達(dá)式
- @Size(min, max) :集合元素的數(shù)量必須在min和max之間
- @CreditCardNumber(ignoreNonDigitCharacters=): 字符串必須是信用卡號,按照美國的標(biāo)準(zhǔn)驗(yàn)證
- @Email: 字符串必須是Email地址
- @Length(min, max) :檢查字符串的長度
- @NotBlank : 只能用于字符串不為null,并且字符串trim()以后length要大于0
- @NotEmpty : 字符串不能為null, 集合必須有元素
- @Range(min, max) :數(shù)字必須大于min, 小于max
- @SafeHtml(whitelistType=,additionalTags=) :字符串必須是安全的html, classpath中要有jsoup包
- @URL(protocol=,host=, port=, regexp=, flags=) : 字符串必須是合法的URL
- @AssertTrue :被注釋的元素必須為 true
- @AssertFalse :被注釋的元素必須為 false
- @DecimalMax(value=, inclusive=) :值必須小于等于(inclusive=true)/小于(inclusive=false)屬性指定的值,也可以注釋在字符串類型的屬性上。
- @DecimalMin(value=, inclusive=) :值必須大于等于(inclusive=true)/小于(inclusive=false)屬性指定的值,也可以注釋在字符串類型的屬性上。
- @Digits (integer, fraction) :數(shù)字格式檢查。integer指定整數(shù)部分的最大長度,fraction指定小數(shù)部分的最大長度
- @Future : 時間必須是未來的
- @Past : 時間必須是過去的
- @Max(value=) : 值必須小于等于value指定的值。不能注解在字符串類型屬性上。
- @Min(value=) : 值必須小于等于value指定的值。不能注解在字符串類型屬性上。
- @ScriptAssert(lang=, script=, alias=) : 要有Java Scripting API 即JSR 223("Scripting for the JavaTM Platform")的實(shí)現(xiàn)
三、@Valid和@Validated的區(qū)別
@Valid是使用Hibernate validation的時候。
@Validated是使用Spring Validator校驗(yàn)機(jī)制(在spring-context依賴下)。
java的JSR303聲明了@Valid這類接口,而Hibernate-validator對其進(jìn)行了實(shí)現(xiàn),@Validation對@Valid進(jìn)行了二次封裝,在使用上并沒有區(qū)別,但在分組、注解位置、嵌套驗(yàn)證等功能上有所不同。
1. 注解位置上
@Validated:用在類型、方法和方法參數(shù)上。但不能用于成員屬性(field)。
@Valid:可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(field)上。
如果@Validated注解在成員屬性上,則會報 不適用于field錯誤。
2. 分組校驗(yàn)
@Validated:提供分組功能,可以在參數(shù)驗(yàn)證時,根據(jù)不同的分組采用不同的驗(yàn)證機(jī)制。
@Valid:沒有分組功能。
(1) 定義分組接口
public interface IGroupA { } public interface IGroupB { }
(2) 定義需要校驗(yàn)的參數(shù)bean
public class Student implements Serializable { @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進(jìn)行驗(yàn)證 @Min(value = 18, message = "年齡不能小于18歲", groups = {IGroupB.class}) private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機(jī)號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
(3) 檢驗(yàn)分組為IGroupA的情況
@RestController public class CheckController { @PostMapping("/stu") public String addStu(@Validated({IGroupA.class}) Student studentBean){ return "add student success"; } }
很明顯,這里對IGroupA是不起作用的,修改為@Validated({IGroupB.class})或@Validated({IGroupA.class, IGroupB.class})。
說明:
不分配groups,默認(rèn)每次都要進(jìn)行驗(yàn)證
對一個參數(shù)需要多種驗(yàn)證方式時,也可通過分配不同的組達(dá)到目的。
3. 組序列
默認(rèn)情況下 不同級別的約束驗(yàn)證是無序的,但是在一些情況下,順序驗(yàn)證卻是很重要。
一個組可以定義為其他組的序列,使用它進(jìn)行驗(yàn)證的時候必須符合該序列規(guī)定的順序。在使用組序列驗(yàn)證的時候,如果序列前邊的組驗(yàn)證失敗,則后面的組將不再給予驗(yàn)證。
(1) 定義組序列
@GroupSequence({Default.class, IGroupA.class, IGroupB.class}) public interface IGroup { }
(2) 需要校驗(yàn)的Bean,分別定義IGroupA對age進(jìn)行校驗(yàn),IGroupB對email進(jìn)行校驗(yàn):
public class Student implements Serializable { @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進(jìn)行驗(yàn)證 @Min(value = 18, message = "年齡不能小于18歲", groups = {IGroupA.class}) private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機(jī)號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤", groups = IGroupB.class) private String email; }
(3) 測試
@RestController public class CheckController { @PostMapping("/stu") public String addStu(@Validated({IGroup.class}) Student studentBean){ return "add student success"; } }
測試發(fā)現(xiàn),如果age出錯,那么對組序列在IGroupA后的IGroupB不進(jìn)行校驗(yàn)。
4. 嵌套校驗(yàn)
一個待驗(yàn)證的pojo類,其中還包含了待驗(yàn)證的對象,需要在待驗(yàn)證對象上注解@Valid,才能驗(yàn)證待驗(yàn)證對象中的成員屬性,這里不能使用@Validated。
(1) 需要約束的bean
public class TeacherBean { @NotEmpty(message = "老師姓名不能為空") private String teacherName; @Min(value = 1, message = "學(xué)科類型從1開始計算") private int type; }
public class Student implements Serializable { @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進(jìn)行驗(yàn)證 @Min(value = 18, message = "年齡不能小于18歲") private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機(jī)號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; @NotNull(message = "任課老師不能為空") @Size(min = 1, message = "至少有一個老師") private List<TeacherBean> teacherBeans; }
上面這樣寫,對teacherBeans只校驗(yàn)了NotNull, 和 Size,并沒有對teacher信息里面的字段進(jìn)行校驗(yàn),如果需要多里面的屬性也進(jìn)行校驗(yàn),可以在teacherBeans中加上 @Valid
@Valid @NotNull(message = "任課老師不能為空") @Size(min = 1, message = "至少有一個老師") private List<TeacherBean> teacherBeans;
四、驗(yàn)證結(jié)果接收
可以Controller的方法入?yún)⑸咸砑覤indingResult參數(shù),用于接收校驗(yàn)后的驗(yàn)證結(jié)果,如果多個校驗(yàn)對象,那么每個@Validated
后面跟著的BindingResult就是這個@Validated的驗(yàn)證結(jié)果,順序不能亂。
@Validated People p, BindingResult result, @Validated Person p2
可能用到的操作:
// result是BindingResult 實(shí)例 if(result.hasErrors()){ List<ObjectError> allErrors = result.getAllErrors(); for(ObjectError error : allErrors){ FieldError fieldError = (FieldError)error; // 屬性 String field = fieldError.getField(); // 錯誤信息 String message = fieldError.getDefaultMessage(); System.out.println(field + ":" + message); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis中resultMap 標(biāo)簽的使用教程
resultMap 標(biāo)簽用來描述如何從數(shù)據(jù)庫結(jié)果集中來加載對象,這篇文章重點(diǎn)給大家介紹mybatis中resultMap 標(biāo)簽的使用,感興趣的朋友一起看看吧2018-07-07Java 判斷兩個字符串是否由相同的字符組成的實(shí)例
今天小編就為大家分享一篇Java 判斷兩個字符串是否由相同的字符組成的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07SpringBoot實(shí)現(xiàn)application配置信息加密
在配置文件中,我們有開發(fā)環(huán)境配置和生產(chǎn)環(huán)境配置,而生產(chǎn)環(huán)境的配置信息是需要做好防護(hù)的,避免外泄,所以本文為大家整理了application配置信息加密的方法,需要的可以參考下2023-07-07一步步教你如何使用Java實(shí)現(xiàn)WebSocket
websocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議,它實(shí)現(xiàn)了瀏覽器與服務(wù)器的全雙工通訊-允許服務(wù)器主動發(fā)起信息個客戶端,websocket是一種持久協(xié)議,http是非持久協(xié)議,下面這篇文章主要給大家介紹了關(guān)于如何使用Java實(shí)現(xiàn)WebSocket的相關(guān)資料,需要的朋友可以參考下2023-05-05