[2core]中间件和过滤器

  • 概述
     最近在尝试做将asp.net webapi项目转移为asp.net core webapi项目的技术试验,今天开始测试认证授权、资源控制、Action与Result控制、以及异常控制的技术变化与请求流程。在asp.net项目中主要采用过滤器(Filter)通过AOP编程模式,拦截客户端发起的请求,然后进行验证,而在asp.net core出现了中间件(Middleware)的概念,且过滤器被归类到mvc命名空间下,因此中间件才是请求管道的正统。

    首先说明,本文仅分析中间件和过滤器的执行顺序和过程(实用为先),不会告诉你为什么会出现中间件以及如何使用,如有此需求,请去官网学习。

    从微软asp.net core官网教程知晓,asp.net core处理请求时,先执行中间件,后执行过滤器,顺序如下图所示:

     

  • 中间件
    1. 设计

      中间件的定义,它是一装配到应用管道以处理请求和响应的组件。在每一个组件中都可以做两件事:

        a)选择是否将请求传递到管道中的下一个组件。

        b)可在管道中的下一个组件前后执行工作。

      请求委托用于生成请求管道,请求委托处理每一个HTTP请求。

      上图展示了中间件完整的请求处理管道顺序,不过我们仅关心Custom middlewares这部分内容,因为我们会忽略asp.net core提供的那套功能,在实际编程中自己实现。

      由于在全新的asp.net core框架里一切资源皆依赖注入化(DI),所以中间件也不例外。要使用定义的中间件,首先把中间件添加IServiceCollection集合中,然后再WebApplication对象的UseMiddleware方法启用。特别注意,使用UseMiddleware方法启用中间件时,一定要注意顺序问题,这是它与过滤器不同之处,框架提供的那些过滤器已经定义好了执行顺序,中间件需要你自己排序。

      以下内容将从五种中间件的定义和使用展示编码顺序和过程

    2. 定义

      a)AuthMiddleware
      作用:权控中间件,用于认证和授权验证。
      代码:

      1     public class AuthMiddleware : IMiddleware
      2     {
      3         public async Task InvokeAsync(HttpContext context, RequestDelegate next)
      4         {
      5             Console.WriteLine("auth before");
      6             await next(context);
      7             Console.WriteLine("auth after");
      8         }
      9     }

      b)ResourceMiddleware

      作用:资源中间件,用于防盗链等。
      代码:

      1     public class ResourceMiddleware : IMiddleware
      2     {
      3         public async Task InvokeAsync(HttpContext context, RequestDelegate next)
      4         {
      5             Console.WriteLine("resource before");
      6             await next(context);
      7             Console.WriteLine("resource after");
      8         }
      9     }

      c)ActionMiddleware

      作用:方法中间件,用于拦截每一个请求的Action方法。
      代码:

      1     public class ActionMiddleware : IMiddleware
      2     {
      3         public async Task InvokeAsync(HttpContext context, RequestDelegate next)
      4         {
      5             Console.WriteLine("action before");
      6             await next(context);
      7             Console.WriteLine("action after");
      8         }
      9     }

      d)ExceptionMiddleware

      作用:异常中间件,进行全局的异常信息收集和处理。
      代码:

      1     public class ExceptionMiddleware : IMiddleware
      2     {
      3         public async Task InvokeAsync(HttpContext context, RequestDelegate next)
      4         {
      5             Console.WriteLine("exception before");
      6             await next(context);
      7             Console.WriteLine("exception after");
      8         }
      9     }

      e)ResultMiddleware

      作用:结果中间件,可以对结构进行格式化处理、数据转换等操作。
      代码:

      1     public class ResultMiddleware : IMiddleware
      2     {
      3         public async Task InvokeAsync(HttpContext context, RequestDelegate next)
      4         {
      5             Console.WriteLine("result before");
      6             await next(context);
      7             Console.WriteLine("result after");
      8         }
      9     }
    3. 使用
       1 using webapi.test.auth.Functions;
       2 using webapi.test.auth.Middlewares;
       3 
       4 var builder = WebApplication.CreateBuilder(args);
       5 
       6 // Add services to the container.
       7 builder.Services.AddControllers();
       8 builder.Services.AddSingleton<IGreeter,Greeter>();
       9 builder.Services.AddSingleton<AuthMiddleware>();
      10 builder.Services.AddSingleton<ResourceMiddleware>();
      11 builder.Services.AddSingleton<ActionMiddleware>();
      12 builder.Services.AddSingleton<ExceptionMiddleware>();
      13 builder.Services.AddSingleton<ResultMiddleware>();
      14 
      15 var app = builder.Build();
      16 // Configure the HTTP request pipeline.
      17 app.UseMiddleware<AuthMiddleware>();
      18 app.UseMiddleware<ResourceMiddleware>();
      19 app.UseMiddleware<ActionMiddleware>();
      20 app.UseMiddleware<ExceptionMiddleware>();
      21 app.UseMiddleware<ResultMiddleware>();
      22 
      23 app.MapControllers();
      24 
      25 app.Run();

       

  • 过滤器
    1. 设计
       通过使用asp.net core中的过滤器,可以在请求处理管道中的特定阶段之前或之后运行功能控制代码。过滤器实际上就是以面向切面编程(AOP)的方式解决编程需求,将大量重复性的代码抽象提取出来,降低业务功能代码的复杂度,使业务功能逻辑编码更加专注,代码结构更加清晰明了。

      注意事项:过滤器适用于Razor Pages、API控制器和具有视图的控制器,但是不能直接用于Razor组件。

      通常过滤器会和特性一起使用,这会是过滤器的使用更加灵活。过滤器分为同步和异步两种类型,实际编程中任意实现一个即可,而不是同时实现,运行时会先查看过滤器是否实现异步接口,如果是则调用该接口,否则调用同步接口的方法。如果在一个类中同时实现异步和不同接口,则仅调用异步方法。

      以下内容将从五种过滤器的定义和使用展示编码顺序和过程
    2. 定义
       a)ApiAuthAttribute

      作用:权控过滤器,用于认证和授权验证。
      代码:

      1     [AttributeUsage(AttributeTargets.Class)]
      2     public class ApiAuthAttribute : Attribute, IAuthorizationFilter
      3     {
      4         public void OnAuthorization(AuthorizationFilterContext context)
      5         {
      6 
      7         }
      8     }

      b)ApiResourceAttribute

      作用:资源过滤器,用于资源缓存、防盗链等。
      代码:

       1     [AttributeUsage(AttributeTargets.Class)]
       2     public class ApiResourceAttribute : Attribute, IResourceFilter
       3     {
       4         public void OnResourceExecuted(ResourceExecutedContext context)
       5         {
       6         }
       7 
       8         public void OnResourceExecuting(ResourceExecutingContext context)
       9         {
      10             
      11         }
      12     }

      c)ApiActionAttribute

      作用:方法过滤器,用于拦截每一个请求的Action方法。
      代码:

       1     [AttributeUsage(AttributeTargets.Class)]
       2     public class ApiActionAttribute : Attribute, IActionFilter
       3     {
       4         public void OnActionExecuting(ActionExecutingContext context)
       5         {
       6             
       7         }
       8         public void OnActionExecuted(ActionExecutedContext context)
       9         {
      10             
      11         }
      12     }

      d)ApiExceptionAttribute

      作用:异常过滤器,进行全局的异常信息收集和处理。
      代码:

      1     [AttributeUsage(AttributeTargets.Class)]
      2     public class ApiExceptionAttribute : Attribute, IExceptionFilter
      3     {
      4         public void OnException(ExceptionContext context)
      5         {
      6             
      7         }
      8     }

      e)ApiResultAttribute

      作用:结果过滤器,可以对结构进行格式化处理、数据转换等操作。
      代码:

       1     [AttributeUsage(AttributeTargets.Class)]
       2     public class ApiResultAtrribute : Attribute, IResultFilter
       3     {
       4         public void OnResultExecuted(ResultExecutedContext context)
       5         {
       6 
       7         }
       8 
       9         public void OnResultExecuting(ResultExecutingContext context)
      10         {
      11 
      12         }
      13     }
    3. 使用
       1     [ApiAuth]
       2     [ApiResource]
       3     [ApiAction]
       4     [ApiException]
       5     [ApiResult]
       6     [ApiController]
       7     [Route("[controller]")]
       8     public class WeatherForecastController : ControllerBase
       9     {
      10            //...
      11     }
    4. 扩展

      由于在asp.net core框架里一切资源皆以DI方式创建和管理,而过滤器则是以Attribute特性标注的方式注册,且又是在运行时注册的,所以面临在过滤器中使用DI资源的问题。

      如何解决?解决这个问题,需要使用TypeFilter和ServiceFilter特性进行标注注册。

      a)两者区别
        ServiceFilter需要对自定义的Filter进行注册,TypeFilter不需要注册。
        ServiceFilter的Filter生命周期由注册时决定,TypeFilter每次都会创建一个新实例。
      b)使用方式
        TypeFilter
      1 [TypeFilter(typeof(ApiException))]
      2 public class Test{
      3     //
      4 }

        ServiceFilter

      1 [ServiceFilter(typeof(ApiException))]
      2 public class Test{
      3     //
      4 }
      5     
      6 public void ConfigureServices(IServiceCollection services){
      7    services.AddSingleton<ApiException>();
      8 }

       

  • 总结
     通过上述内容分析得出结论,在webapi编码过程中,应该以中间件形式实现某些需要的功能,毕竟过滤器与依赖注入搭配的不是很方便,而且过滤器已经被归类于aspnetcore.mvc命名空间下了。
    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章