[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编码过程中,应该以中间件形式实现某些需要的功能,毕竟过滤器与依赖注入搭配的不是很方便,Minimal API不支持过滤器,而且过滤器已经被归类于aspnetcore.mvc命名空间下了。

测试代码:https://gitee.com/kinbor/jks.core.test.middlewareandfilter
posted @   oO归客Oo  阅读(514)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Blazor Hybrid适配到HarmonyOS系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
点击右上角即可分享
微信分享提示