【使用篇二】SpringBoot服務端數據校驗(8)

對於任何一個應用而言,客戶端作的數據有效性驗證都不是安全有效的,而數據驗證又是一個企業級項目架構上最爲基礎的功能模塊,這時候就要求咱們在服務端接收到數據的時候也對數據的有效性進行驗證。爲何這麼說呢?每每咱們在編寫程序的時候都會感受後臺的驗證可有可無,畢竟客戶端已經作過驗證了,後端不必在浪費資源對數據進行驗證了,但偏偏是這種思惟最爲容易被別人鑽空子。畢竟只要有點開發經驗的都知道,咱們徹底能夠模擬 HTTP 請求到後臺地址,模擬請求過程當中發送一些涉及系統安全的數據到後臺,後果可想而知....html

驗證分兩種:對封裝的Bean進行驗證  或者  對方法簡單參數的驗證。java

說明:SpringBoot 中使用了 Hibernate-validate 校驗框架做爲支持git

1. 建立項目Maven Project,修改pom.xmlweb

<properties>
        <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
        <!-- jstl -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>
    <!-- jasper:jsp引擎 -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

2. 在src/main/resources目錄下新建application.properies,並添加全局配置正則表達式

#jsp視圖映射配置
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

3. 建立實體類並添加校驗註解spring

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import org.hibernate.validator.constraints.Length;

public class User {
    
    private Integer userId;
    @NotBlank
    @Length(min=2,max=10)
    private String userName;
    @NotBlank
    private String password;
    private Integer age;
    @Email
    private String email;
    public User() {
        
    }
    public User(Integer userId, String userName, String password, Integer age, String email) {
        this.userId = userId;
        this.userName = userName;
        this.password = password;
        this.age = age;
        this.email = email;
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    
    public String getEmail() {
        return email;
    }
}

4. 編寫Controllerapache

import javax.validation.Valid;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

@RestController
@RequestMapping("/user")
public class UserController {
    
    /**
     * 頁面跳轉
     */
    @RequestMapping("/{page}")
    public Object showPage(Model model,@PathVariable String page, User user){
        ModelAndView view = new ModelAndView();
        view.addObject(model);
        view.setViewName(page);
        return view;
    }
    
    /*
     * @Validated 開啓對 User對象的數據校驗 (User對象須要添加註解)
     * BindingResult:封裝了校驗的結果,會自動添加到model對象進行傳遞
     * 注意:@Validated 和 BindingResult 是一一對應的,若是有多個@Valid,那麼每一個@Validated後面跟着的BindingResult就是這個@Validated的驗證結果,順序不能亂
     */
    @RequestMapping("/addUser")
    public Object addUser(Model model, @Validated User user, BindingResult result){
        ModelAndView view = new ModelAndView();
        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);
                //model的錯誤信息暫時不知怎麼獲取對應的消息,因此解析BindingResult後,單獨放入model,在頁面再獲取
                model.addAttribute(field, message);
                
            }
            view.addObject(model);
            view.setViewName("input");
            return view;
        }
        view.setViewName("ok");
        return view;
    }
}

5. 在src/main目錄下建立webapp/WEB-INF/jsp目錄,在jsp文件夾下編寫視圖jsp後端

(1) 表單輸入頁面:input.jsptomcat

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>添加用戶</title>
</head>
<body>
    <h3>添加用戶:</h3>
    <form action="/user/addUser" method="post">
        用戶姓名:<input type="text" name="userName" /><font color="red">${userName }</font><br/>
        用戶密碼:<input type="password" name="password" /><font color="red">${password }</font><br/>
        用戶年齡:<input type="text" name="age" /><font color="red">${age }</font><br/>
        用戶郵箱:<input type="text" name="email" /><font color="red">${email }</font><br/>
        <input type="submit" value="肯定" /><br />
    </form>
</body>
</html>

(2) 操做成功頁面:ok.jsp安全

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>操做成功</title>
</head>
<body>
    <h5>操做 成功</h5>
</body>
</html>

6. 自定義錯誤信息提示

注:此處也可不在配置文件中配置,直接在驗證的massage中寫。

(1) 在resources 目錄下新建提示信息配置文件ValidationMessages.properties,文件名是固定的,由於SpringBoot自動讀取classpath中的ValidationMessages.properties裏的錯誤信息。

ValidationMessages.properties 文件的編碼爲ASCII,格式爲 key=value 。

#用戶名不能爲空
user.userName.notBlank=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
#密碼不能爲空
user.password.notBlank=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A

(2) 修改實體類

private Integer userId;
@NotBlank(message="{user.userName.notBlank}")
@Length(min=2,max=10)
private String userName;
@NotBlank(message="{user.password.notBlank}")
private String password;
private Integer age;
@Email
private String email;

7. 方法參數中簡單類型的校驗

(1) 在Controller類上添加@Validated註解,只有添加這個,方法參數中的@Email等註解才能起做用

(2) 在Controller的方法參數前加上註解,能夠加多個

@RequestMapping("/addUser2")
    public Object addUser(@NotBlank(message = "name 不能爲空") @Length(min = 2, max = 10, message = "name 長度必須在 {min} - {max} 之間")String userName){
        ModelAndView view = new ModelAndView();
        view.setViewName("ok");
        return view;
    }

以上方法會拋出ConstraintViolationException異常:

javax.validation.ConstraintViolationException: addUser.userName: name 不能爲空, addUser.userName: name 長度必須在 2 - 10 之間

不管是對象校驗仍是簡單類型校驗,若是存在須要校驗多個,就會很麻煩,可用異常的方式進行統一處理,後續再講。

8. 經常使用的Validation註解

@NotNull			值不能爲空
@Null				值必須爲空
@Pattern(regex=)	字符串必須匹配正則表達式
@Size(min, max)		集合元素的數量必須在min和max之間
@CreditCardNumber(ignoreNonDigitCharacters=)	字符串必須是信用卡號,按照美國的標準驗證
@Email				字符串必須是Email地址
@Length(min, max)	檢查字符串的長度
@NotBlank			字符串不能爲空串(去掉首尾空格)
@NotEmpty			字符串不能爲null, 集合必須有元素
@Range(min, max)	數字必須大於min, 小於max
@SafeHtml			字符串必須是安全的html
@URL				字符串必須是合法的URL
@AssertFalse		值必須是false
@AssertTrue			值必須是true
@DecimalMax(value=, inclusive=)	值必須小於等於(inclusive=true)/小於(inclusive=false)屬性指定的值,也能夠註釋在字符串類型的屬性上。
@DecimalMin(value=, inclusive=)	值必須大於等於(inclusive=true)/小於(inclusive=false)屬性指定的值,也能夠註釋在字符串類型的屬性上。
@Digist(integer=,fraction=)	數字格式檢查。integer指定整數部分的最大長度,fraction指定小數部分的最大長度
@Future				時間必須是將來的
@Past				時間必須是過去的
@Max(value=)		值必須小於等於value指定的值。不能註解在字符串類型屬性上。
@Min(value=)		值必須小於等於value指定的值。不能註解在字符串類型屬性上。

9. 總結

須要注意的:

(1) 對象的校驗,錯誤信息在jsp頁面如何獲取?

(2) 方法參數中簡單類型的校驗,Controller類上必須添加@Validated註解。

(3) 自定義校驗的提示信息,ValidationMessages.properties的名稱及文件的編碼

相關文章
相關標籤/搜索