美文网首页陈大志的 Java 笔记spring boot
SpringBoot 实战 (十五) | 服务端参数校验之一

SpringBoot 实战 (十五) | 服务端参数校验之一

作者: JavaFish | 来源:发表于2019-03-03 22:18 被阅读195次

    前言

    估计很多朋友都认为参数校验是客户端的职责,不关服务端的事。其实这是错误的,学过 Web 安全的都知道,客户端的验证只是第一道关卡。它的参数验证并不是安全的,一旦被有心人抓到可乘之机,他就可以有各种方法来摸拟系统的 Http 请求,访问数据库的关键数据。轻则导致服务器宕机,重则泄露数据。所以,这时就需要设置第二道关卡,服务端验证了。

    老项目的服务端校验

    @RestController
    @RequestMapping("/student")
    public class ValidateOneController {
    
        @GetMapping("/id")
        public Student findStudentById(Integer id){
            if(id == null){
                  logger.error("id 不能为空!");
                  throw new NullPointerException("id 不能为空");
            }
            return studentService.findStudentById(id);
        }
    }
    

    看以上代码,就一个的校验就如此麻烦。那我们是否有好的统一校验方法呢?鉴于 SpringBoot 无所不能。答案当然是有的。

    其中,Bean Validator 和 Hibernate Validator 就是两套用于验证的框架,二者都遵循 JSR-303 ,可以混着用,鉴于二者的某些 Validator 注解有差别,例如 @Length 在 Bean Validator 中是没有的,所以这里我选择混合用。

    JSR-303

    JSR-303 是JAVA EE 6 中的一项子规范,叫做 Bean Validation,Hibernate Validator 是 Bean Validation 的参考实现, Hibernate Validator 提供了 JSR 303 规范中所有内置 Constraint(约束) 的实现,除此之外还有一些附加的 Constraint 。这些 Constraint (约束) 全都通过注解的方式实现,请看下面两个表。

    Bean Validation 中内置的约束:

    注解 作用
    @Null 被注解参数必须为空
    @NotNull 被注解参数不能为空
    @AssertTrue 被注解参数必须为 True
    @AssertFalse 被注解参数必须为 False
    @Min(value) 被注解参数必须是数字,且其值必须大于等于 value
    @Max(value) 被注解参数必须是数字,且其值必须小于等于 value
    @DecimaMin(value) 被注解参数必须是数字,且其值必须大于等于 value
    @DecimaMax(value) 被注解参数必须是数字,且其值必须小于等于 value
    @Size(max, min) 被注解参数大小必须在指定范围内
    @Past 被注解参数必须是一个过去的日期
    @Future 被注解参数必须是一个将来的日期
    @Pattern(value) 被注解参数必须符合指定的正则表达式
    @Digits(integer, fraction) 被注解参数必须是数字,且其值必须在可接受范围内
    @NotBlank 被注解参数的值不为空(不为 null、去除首位空格后长度为 0),不同于 @NotEmpty,@NotBlank 只应用于字符串且在比较时会去除字符串的空格

    Hibernate Validator 附加的约束:

    注解 作用
    @NotEmpty 被注解参数的值不为 null 且不为空(字符串长度不为0、集合大小不为0)
    @Email 被注解参数必须是电子邮箱地址
    @Length 被注解的字符串长度必须在指定范围内
    @Range 被注解的参数必须在指定范围内

    准备工作

    • SpringBoot 2.1.3
    • IDEA
    • JDK8

    Pom 文件依赖

    <!-- web 启动类 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- test 单元测试类 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <!-- lombok 依赖用于简化 bean -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    

    实体类

    用于测试,加入了参数校验规则。

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student {
    
        private Integer id;
    
        @NotBlank(message = "学生名字不能为空")
        @Length(min = 2, max = 10, message = "name 长度必须在 {min} - {max} 之间")
        private String name;
    
        @NotNull(message = "年龄不允许为空")
        @Min(value = 0, message = "年龄不能低于 {value} 岁")
        private Integer age;
    }
    

    Controller 层

    写了两个方法,一个用于校验普通参数,一个用于校验对象

    @Validated //开启数据校验,添加在类上用于校验方法,添加在方法参数中用于校验参数对象。(添加在方法上无效)
    @RestController
    @RequestMapping("/student")
    public class ValidateOneController {
    
        /**
         * 普通参数校验
         * @param name
         * @return
         */
        @GetMapping("/name")
        public String findStudentByName(@NotBlank(message = "学生名字不能为空")
        @Length(min = 2, max = 10, message = "name 长度必须在 {min} - {max} 之间")String name){
            return "success";
        }
    
        /**
         * 对象校验
         * @param student
         * @return
         */
        @PostMapping("/add")
        public String addStudent(@Validated @RequestBody Student student){
            return "success";
        }
    }
    

    Postman 测试

    校验普通参数测试结果:

    下图可以看见,我没有在 http://localhost:8080/student/name 地址后添加 name 参数,传到后台马上就校验出异常了。而这个异常信息就是我定义的校验异常信息。

    校验普通参数测试结果

    校验对象测试结果:

    校验对象测试截图

    结果有点长:

    下图可以看见,我访问 http://localhost:8080/student/add 传入了参数对象,但对象是不能通过校验规则的,比如 age 参数为负数,name 参数长度太大,传到后台马上就校验出异常了。而这个异常信息就是我定义的校验异常信息。

    校验对象测试结果

    完整代码

    https://github.com/turoDog/Demo/tree/master/springboot_validateone_demo

    如果觉得对你有帮助,请给个 Star 再走呗,非常感谢。

    后语

    如果本文对你哪怕有一丁点帮助,请帮忙点好看。你的好看是我坚持写作的动力。

    另外,关注之后在发送 1024 可领取免费学习资料。

    资料详情请看这篇旧文:Python、C++、Java、Linux、Go、前端、算法资料分享

    一个优秀的废人

    相关文章

      网友评论

        本文标题:SpringBoot 实战 (十五) | 服务端参数校验之一

        本文链接:https://www.haomeiwen.com/subject/vgkmuqtx.html