《ASP.NET Core技术内幕与项目实战》精简集-高级组件4.3:请求数据校验

本节内容,涉及到8.3(P269-P272),以WebApi说明为主。主要NuGet包:

  • 内置命名空间:System.ComponentModel.DataAnnotations
  • FluentValidation.AspNetCore(数据检验框架) 

 

一、请求数据检验的作用

1、客户端和服务端进行数据交互时,需要对请求数据进行检验,以保证数据安全和用户体验。现代的前端框架,一般都会在提交数据前,在客户端先进行一次检验。但为了提高安全性,在服务端应该进行一次数据检验兜底。

2、服务端检验有两个方案,一是使用AspNetCore内置的数据检验,在System.ComponentModel.DataAnnotations,以特性标注的方式进行。二是使用第三方库FluentValidation,FluentValidation不仅可以用于AspNetCore,还可以用于控制台、WPF、Blazor等项目中。实际开发中,也主要使用FluentValidation,一是检验规则各丰富,二是实现模型与规则的解耦。

3、FluentValidation的校验规则非常丰富,可以查看官方文档

 

 

二、AspNetCore内置的数据检验

 1 //创建一个模型类,标注校验特性
 2 //LoginRequest.cs
 3 public class LoginRequest: IValidatableObject
 4 {
 5     [Required(ErrorMessage ="邮箱必填")]
 6     [EmailAddress(ErrorMessage ="请输入正确的邮箱")]
 7     public string Email { get; set; }
 8     
 9     [Required]
10     public string Password { get; set; }
11     [Required]
12     public string Password2 { get; set; }
13 
14     public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
15     {
16         if (Password != Password2)
17         {
18             yield return new ValidationResult("密码必须一致!");
19         }
20     }
21 }
22 
23 
24 //创建一个action,将LoginRequest作为请求参数
25 //在Swagger中输入不符合要求的json,测试检验结果
26 //TestController.cs
27 [ApiController]
28 [Route("api/[controller]/[action]")]
29 public class TestController: ControllerBase
30 {
31     [HttpPost]
32     public void Login(LoginRequest loginRequest)
33     {
34         Console.WriteLine($"Email:{loginRequest.Email},Password:{loginRequest.Password}");
35     }
36 }

代码解读:

3行:实现IValidatableObject接口,主要目的是自定义一个检验规则(在14-20行)。如果不自定义检验规则,可以不需要实现这个接口

5,6,9,11行:分别对属性进行了必填、EMAIL格式等检验标注

14-20行:实现Validate方法,返回值是ValidationResult集合,我们通过yield return迭代器方式返回验证结果

 

 

三、FluentValidation数据校验

 1 //第一步:安装Nuget包,FluentValidation.AspNetCore
 2 
 3 //第二步:注册FluentValidation服务
 4 //Program.cs
 5 builder.Services.AddFluentValidation(fv =>
 6 {
 7      Assembly assembly = Assembly.GetExecutingAssembly();
 8     fv.RegisterValidatorsFromAssembly(assembly);
 9 });
10 
11 //第三步:创建模型类,同上例(注意,不需要特性标注)
12 //LoginRequest.cs
13 
14 //第四步,创建模型类的校验类
15 //LoginRequestValidator.cs
16 public class LoginRequestValidator: AbstractValidator<LoginRequest>
17 {
18     public LoginRequestValidator()
19     {
20         RuleFor(l => l.Email).NotNull().EmailAddress()
21             .Must(v => v.EndsWith("@qq.com") || v.EndsWith("@163.com"))
22             .WithMessage("只支持QQ和163邮箱");
23 
24         RuleFor(l => l.Password).NotNull().Length(3, 10).WithMessage("密码长度必须介于3-10之间")
25             .Equal(l => l.Password2).WithMessage("两次密码必须一致");
26 
27     }
28 }
29 
30 //第五步:创建一个action来验证
31 [ApiController]
32 [Route("api/[controller]/[action]")]
33 public class TestController: ControllerBase
34 {
35     private readonly IValidator<LoginRequest> _validator;
36     private readonly ILogger<TestController> _logger;
37     public TestController(IValidator<LoginRequest> validator, ILogger<TestController> logger)
38     {
39         _validator = validator;
40         _logger = logger;
41     }
42 
43     [HttpPost]
44     public async void Login(LoginRequest loginRequest)
45     {
46         var result = await _validator.ValidateAsync(loginRequest);
47         if (!result.IsValid)
48         {
49             foreach (var failure in result.Errors)
50             {
51                 _logger.LogError("属性 " + failure.PropertyName + " 错误信息: " + failure.ErrorMessage);
52             }
53         }
54 
55     }
56 }

代码解读:

7-8行:通过反射获得程序集,RegisterValidatorsFromAssembly方法把指定程序集中,继承AbstractValidator<T>泛型类的检验类都注册到容器中

16行:校验类的命名约定为“模型类+Validator”,继承AbstractValidator<T>泛型类,泛型参数为需要检验的模型类

18-27行:在构造函数中,创建校验规则。每个需要检验的属性,对应一组RuleFor调用,可以链式调用。WithMessage为错误信息,对应它之前的规则检验结果。

18行:在构造函数中,可以参数方式直接注入其它系统服务,如可以注入DbContext,如下所示:

public LoginRequestValidator(TestDbContext ctx){ RuleFor(l=>l.UserName).Must(name=>ctx.Users.Any(u=>u.UserName = name)); }

 

特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍

 

posted @ 2022-11-03 23:17  functionMC  阅读(215)  评论(0编辑  收藏  举报