本文介绍: 本文介绍在SpringBoot使用进行接口参数校验方法。首先解决为什么要进行接口参数校验、为什么后端需要进行参数校验、为什么使用参数校验框架问题。接着详细介绍了在SpringBoot使用进行参数校验的方法,并列出了一些常用注解最后本文解决了当前端发送请求中有些参数需要进行校验时应该怎么办问题

本文介绍SpringBoot使用 Spring Validation 进行接口参数校验的方法。首先解决了为什么要进行接口参数校验、为什么后端需要进行参数校验、为什么使用参数校验框架等问题。接着详细介绍了在 SpringBoot使用 Spring Validation 进行参数校验的方法,并列出了一些常用注解最后本文解决了当前端发送请求中有些参数不需要进行校验时应该怎么办的问题。

1. 疑问

1.1. 为什么要进行接口参数校验?

接口参数校验是指对于接口传入的参数进行检查验证,以确保参数的合法性和正确性。这是确保系统稳定性、安全性可靠性的重要措施

举例

  1. 假设我们一个注册接口用户需要填写用户名密码邮箱地址。如果我们没有进行参数校验,那么用户可以随意输入任何内容,包括非法字符恶意代码,这可能会导致系统崩溃数据泄露安全问题。如果我们对参数进行校验,就可以避免这些问题,同时提高系统可靠性安全性

  2. 一个例子支付接口,如果我们没有对金额订单号支付渠道进行校验,那么可能出现支付失败重复支付或者支付金额错误的情况。通过对参数进行校验,可以避免这些问题,同时提高支付的可靠性安全性

总之,接口参数校验是保证系统安全可靠稳定的必要措施可以避免非法输入恶意攻击数据泄露等问题。

1.2. 为什么在前端已经校验了请求参数,后端的接口还需要进行参数校验呢,这样不是多此一举吗?

虽然前端已经对请求参数进行了校验,但是前端只是为了提高用户体验和减轻服务器的负担而进行的简单校验,并不能完全保证数据安全性和正确性。因此,后端也需要对参数进行校验,以确保数据的合法性和正确性,避免恶意攻击和数据泄露等问题。

举例

  1. 假设我们一个在线购物平台后端接口,前端需要传入商品 ID 和购买数量,前端已经进行了简单的校验,比如购买数量必须是正整数。但是,如果一个恶意用户手动构造一个请求,将购买数量改成负数或者 0 ,那么前端就无法阻止这个请求这个非法请求就会到达后端,如果后端没有进行参数校验,就可能导致订单错误库存错误或者支付异常等问题。因此,后端也需要对参数进行校验,以确保数据的合法性和正确性。

  2. 一个例子登录接口,前端可能会对用户名和密码进行简单的校验,比如密码长度必须大于等于 6 位。但是,如果后端没有对参数进行校验,那么可能出现 SQL 注入XSS 攻击等问题。比如,一个恶意用户可能会在用户名或密码加入一些恶意代码,从而窃取用户信息或者破坏系统。通过对参数进行校验,可以避免这些问题,提高系统安全性可靠性

1.3. 我们可以使用 if else 进行参数校验,为什么要使用参数校验框架呢?

虽然使用 if else 进行参数校验可以实现基本的校验功能,但是这种方式存在以下几个问题:

  1. 代码冗余:如果需要对多个接口进行参数校验,就需要在每个接口中编写相同的校验逻辑代码冗余维护成本高
  2. 可读性差:如果校验逻辑比较复杂,那么使用 if else 进行校验的代码可读性较差,不利于代码维护优化
  3. 安全性差:如果使用 if else 进行校验,那么恶意用户可能利用漏洞绕过校验,从而导致安全问题。

因此,使用参数校验框架可以有效解决上述问题,具有以下几个优点:

  1. 简化代码:使用参数校验框架可以简化校验逻辑,减少代码冗余,提高代码的可读性和可维护性
  2. 提高安全性:参数校验框架可以避免参数注入SQL 注入XSS 攻击等安全问题,提高系统安全性和可靠性
  3. 提高效率:使用参数校验框架可以提高开发效率,减少开发时间成本,并且可以方便地进行扩展定制

总之,使用参数校验框架可以有效地提高系统安全性、可靠性可维护性,减少代码冗余,提高开发效率,是开发过程不可或缺的一部分

2. 为什么要使用 Spring Validation 权限校验框架

哪些参数校验框架呢?

以下是几个常用的参数校验框架:

  1. Hibernate ValidatorHibernate Validator 是一个基于 Bean Validation 标准的参数校验框架,可以实现Java Bean 属性的校验,支持多种校验注解自定义校验规则
  2. Spring ValidationSpring ValidationSpring 框架提供的参数校验框架,基于 Bean Validation 标准,可以实现Java Bean 属性和方法参数的校验,支持多种校验注解自定义校验规则
  3. Apache Commons ValidatorApache Commons Validator 是一个通用的参数校验框架,支持多种校验规则和自定义校验规则,可以实现字符串数字日期数据类型的校验。
  4. JSR-303JSR-303Java EE 6定义Bean Validation 标准,提供了一套参数校验规范API,可以实现Java Bean 属性的校验,支持多种校验注解和自定义校验规则
  5. Bean-ValidationBean-Validation一款轻量级的参数校验框架,基于 JSR-303 标准,可以实现Java Bean 属性的校验,支持多种校验注解和自定义校验规则

这些框架都可以实现对参数的校验,提供了一套完整的校验规范API ,可以有效地避免非法参数和恶意攻击,提高系统的安全性和可靠性。根据不同业务需求技术栈,可以选择不同的框架进行参数校验。

为什么使用 Spring Validation

  1. 基于 Bean Validation 标准:Spring Validation基于 Bean Validation 标准的参数校验框架,可以实现Java Bean 属性和方法参数的校验,提供了一套完整的校验规范API,可以很方便地进行扩展定制
  2. 支持多种校验注解:Spring Validation 支持多种校验注解,比如 @NotNull、@Size、@Min、@Max 等,可以满足不同的校验需求,同时也支持自定义校验注解。
  3. 集成方便:Spring ValidationSpring 框架提供的参数校验框架,与 Spring 框架集成非常方便,可以通过简单的配置实现参数校验。
  4. 可扩展性强:Spring Validation 提供了很好的扩展性,可以自定义校验注解和校验器,满足不同的校验需求
  5. 可读性高:Spring Validation 的校验注解非常简洁明了,代码可读性高,可以很方便地查看维护校验逻辑

总之,使用 pring Validation 参数校验框架可以提高代码的可读性和可维护性,减少代码冗余,提高开发效率,同时还可以有效地避免非法参数和恶意攻击,提高系统的安全性和可靠性

3. 在 SpringBoot 中使用 Spring Validation

  1. 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  1. 定义控制器
@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    @PostMapping("/add")
    public User addUser(@RequestBody @Valid User user) {
        // ...
    }
}

addUser 方法的参数列表中使用 @Valid 注解进行参数校验,@RequestBody 注解用于请求体中的 JSON 对象自动映射Java 对象

注意

  1. 定义实体类
public class User {

    @NotBlank(message = "用户名不能为空")
    private String username;

    @NotBlank(message = "密码不能为空")
    private String password;

    @Email(message = "邮箱格式不正确")
    private String email;

    // 省略 getter 和 setter 方法
}

User 类的属性上使用校验注解,例如 @NotBlank、@Email 等,message 属性用于指定校验失败时的错误提示信息

  1. 定义全局异常处理器

控制器方法的参数校验失败时,会抛出 MethodArgumentNotValidException 异常,此时可以通过定义全局异常处理器中的 handleMethodArgumentNotValidException 方法来处理该异常。

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        StringBuilder errorMsg = new StringBuilder();
        for (ObjectError error : allErrors) {
            errorMsg.append(error.getDefaultMessage()).append("; ");
        }
        return Result.fail(errorMsg.toString());
    }

    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        return Result.fail(e.getMessage());
    }
}

GlobalExceptionHandler 类中添加MethodArgumentNotValidException 异常的处理,将校验失败的错误提示信息封装Result 对象返回客户端

  1. 测试

使用 Postman 或其他工具/user/add 接口发送 POST 请求,请求体中需要包含 usernamepasswordemail 三个参数。如果参数校验失败,接口将返回错误提示信息例如,当 username 为空时,接口将返回以下错误信息

{
    "code": 1,
    "msg": "参数校验失败",
    "data": "用户名不能为空; "
}

通过使用注解和异常处理器,可以非常方便地实现参数校验功能,并将校验结果返回给客户端

4. Spring Validation 的常用注解

Spring Validation 提供了很多注解,用于对参数进行校验。

@NotNull(message = "用户名不能为空")
private String username;
@NotBlank(message = "用户名不能为空")
private String username;
@Size(min = 6, max = 20, message = "密码长度必须在6-20个字符之间")
private String password;

@Size(min = 1, max = 10, message = "至少选择一个爱好,最多选择10个")
private List<String> hobbies;

@Size(min = 1, max = 3, message = "至少选择一个菜,最多选择3个")
private String[] dishes;
@Min(value = 1, message = "年龄必须大于等于1岁")
@Max(value = 150, message = "年龄必须小于等于150岁")
private Integer age;
@DecimalMin(value = "0.01", message = "价格不能低于0.01元")
@DecimalMax(value = "9999.99", message = "价格不能超过9999.99元")
private BigDecimal price;
@Pattern(regexp = "^[a-zA-Z0-9]{4,20}$", message = "用户名必须由4-20个字母数字组成")
private String username;
@Email(message = "请输入正确的邮箱地址")
private String email;
public class User {
    @NotBlank(message = "用户名不能为空")
    private String username;

    @Valid
    private Address address;

    // getter 和 setter 方法省略
}

public class Address {
    @NotBlank(message = "所在城市不能为空")
    private String city;

    @NotBlank(message = "详细地址不能为空")
    private String detail;

    // getter 和 setter 方法省略
}

这些注解可以也用于控制器的方法参数校验。

@RestController
@Validated
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
        // 处理请求,创建用户
        return ResponseEntity.ok(user);
    }
}

在上面的示例中,@Valid 注解用于标记 User 对象需要进行校验。在方法执行时,Spring自动根据 User 对象的属性上的校验注解对其进行校验,如果校验不通过,则会抛出 ConstraintViolationException 异常。

需要注意的是,为了使校验注解生效控制器类需要添加 @Validated 注解。

5. 前端发送的请求,有些参数不需要进行校验怎么办

前端发送的请求,有些参数不需要进行校验。比如我们更新一个用户,而我们对 JavaBean所有参数都进行了校验,那这个请求就被拒绝了,这种请求我们应该怎么办?

当我们在校验接口参数时,有些 JavaBean 参数不需要进行校验,可以使用 Spring Validation 提供的 @Validated 和 @Valid 注解结合分组校验来实现。

首先,在 JavaBean 参数上使用校验注解时,可以为注解指定一个分组示例代码如下

public class User {

    @NotBlank(message = "用户名不能为空", groups = {Create.class, Update.class})
    private String username;

    @NotBlank(message = "密码不能为空", groups = {Create.class})
    private String password;

    @NotBlank(message = "手机号不能为空", groups = {Create.class})
    private String mobile;

    // getter 和 setter 方法省略
}

在上面的示例中,@NotBlank 注解被分为两个组:CreateUpdate对应创建更新操作。这样,当我们对 User 对象进行校验时,只需要指定需要校验的组即可示例代码如下

@RestController
@Validated
public class UserController {

    @PostMapping("/users")
    public ResponseEntity<User> createUser(@Validated(Create.class) @RequestBody User user) {
        // 处理请求,创建用户
        return ResponseEntity.ok(user);
    }

    @PutMapping("/users/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @Validated(Update.class) @RequestBody User user) {
        // 处理请求,更新用户
        return ResponseEntity.ok(user);
    }
}

在上面的示例中,@Validated 注解用于标记控制器类需要进行校验,并通过 groups 属性指定需要校验的分组@Validated 注解可以作用控制器类或方法上。@Validated 注解和 @Valid 注解的区别在于,@Validated 注解可以指定需要校验的分组,而 @Valid 注解不支持分组校验。

这样,当我们在创建用户时,只会校验 usernamepasswordmobile 参数,而在更新用户时,只会校验 username 参数,不会对 passwordmobile 参数进行校验。

原文地址:https://blog.csdn.net/weixin_51262499/article/details/129910551

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_49461.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注