参数校验好,安全没烦恼

前言

后端开发API的时候经常遇到要验证前端传过来的参数。一个一个的校验未免太不优雅了。那么使用springboot怎么优雅解决呢?

传统的校验参数的方法

传统的方式,会将前端传过来的参数一一校验,虽然也能达到效果,但是耗费了精力,代码也比较长

    @RequestMapping("add")
    public R add( @RequestBody Banner banner){
        R r =new R<>();
        if (StringUtils.isEmpty(banner.getName())) {
            return r.fail("名字不能为空");
        }
        if (StringUtils.isEmpty(banner.getUrl())) {
            return r.fail("url不能为空");
        }
        //假装有业务操作
        return r.success("ok");
    }

更简洁的校验方式

我们可以使用spring提供的validation组件


      org.springframework.boot
      spring-boot-starter-validation

首先需要设计一个入参的对象

@Data
public class Banner implements Serializable {

    /**
     * 名字
     */
    private String name;

    /**
     * 链接
     */
    private String url;
}

当我们需要对指定的入参进行校验的时候,使用注解就能指定校验规则(支持多个)
下面是封装好的规则,找到需要的直接使用就可以了

注解 规则
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max,min) 被注释的元素的大小必须在指定的范国内
@Digits (integer, fraction) 被注释的元素必须是一个数宇,其值必须在可接受的范田内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern (value) 被注释的元素必须符合指定的正则表达式

当我们需要name、url这两个参数不能为空时,选择加上@NotNull注解就可以了
然后再完善下controller,在入参的地方加上@Vaild,就代表需要做参数校验

@RequestMapping("banner")
@RestController
public class BannerController {

    @RequestMapping("add")
    public R add(@Valid @RequestBody Banner banner){
        R r =new R<>();
        //假装有业务逻辑代码在这里调用
        return r.success("ok");
    }
}

参数校验效果

当我们把参数设置为不能为空,就可以启动web服务试试效果了

缺参数的时候

完整参数的时候

上面图片展示了,有参数校验通过的情况,和参数校验不通过的情况。我们能看到,在校验不通过的时候,响应的code 是400
这样虽然参数校验到位了,但是报错也不够友好,不利于后续排查问题。所以我们希望当参数不合规时,把错误的的原因通过接口返回。

优化返回参数

我们在控制台发现刚刚出现参数校验不通过的时候,实际上是抛出了一个异常

抛出异常

我们可以试试将这个异常捕获,然后将错误信息抓出来返回给客户端
首先来看下异常里面有哪些我们可以使用的信息
1. 全局异常控制

@ControllerAdvice
@ResponseBody
public class ExceptionHandle {

    @ExceptionHandler
    public R ParamExceptionHandle(MethodArgumentNotValidException e){
        System.out.println(e);//这里打断点,看看异常类里有什么东西
        return null;
    }
}

通过将异常捕获器,看看异常里面的内容

错误信息

从错误消息中我们可以看到有校验不通过的字段名默认的错误消息
那我们把这两个字段组合一下,就变成了"url"+"字段"+"不能为null”
2. 下面进行对全局异常捕获的改造

@Slf4j
@ControllerAdvice
@ResponseBody
public class ExceptionHandle {

    @ExceptionHandler
    public R ParamExceptionHandle(MethodArgumentNotValidException e){
        log.info("捕获参数校验异常",e);
        List failError= new ArrayList<>();
        for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
            String field = fieldError.getField();//字段名
            String defaultMessage = fieldError.getDefaultMessage();
            StringBuilder sb=new StringBuilder();
            sb.append("参数:").append(field).append(",校验异常。").append("原因:").append(defaultMessage);
            failError.add(sb.toString());
        }
        R> r=new R<>();
        return r.fail(failError.toString());
    }
}

3.重启服务看看效果

单个参数校验不通过

多个参数校验不通过

参数校验通过

尾巴

spring提供的validate工具结合全局异常管理,可以让控制器瘦身,减少代码量的同时,在设计入参字段的同时设计校验规则,更符合直觉,不容易出错。感谢阅读!如果觉得我内容还不错的话,记得关注和点赞

你可能感兴趣的:(参数校验好,安全没烦恼)