[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处理请求时,先执行中间件,后执行过滤器,顺序如下图所示:

中间件

设计

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

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

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

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

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

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

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

定义

  1. AuthMiddleware
    作用:权控中间件,用于认证和授权验证。
    代码:
    public class AuthMiddleware : IMiddleware
        {
            public async Task InvokeAsync(HttpContext context, RequestDelegate next)
            {
                Console.WriteLine("auth before");
                await next(context);
                Console.WriteLine("auth after");
            }
        }
  2. ResourceMiddleware
    作用:资源中间件,用于防盗链等。
    代码:
    public class ResourceMiddleware : IMiddleware
        {
            public async Task InvokeAsync(HttpContext context, RequestDelegate next)
            {
                Console.WriteLine("resource before");
                await next(context);
                Console.WriteLine("resource after");
            }
        }

  3. ActionMiddleware
    作用:方法中间件,用于拦截每一个请求的Action方法。
    代码:
    public class ActionMiddleware : IMiddleware
        {
            public async Task InvokeAsync(HttpContext context, RequestDelegate next)
            {
                Console.WriteLine("action before");
                await next(context);
                Console.WriteLine("action after");
            }
        }

  4. ExceptionMiddleware
    作用:异常中间件,进行全局的异常信息收集和处理。
    代码:
    public class ExceptionMiddleware : IMiddleware
        {
            public async Task InvokeAsync(HttpContext context, RequestDelegate next)
            {
                Console.WriteLine("exception before");
                await next(context);
                Console.WriteLine("exception after");
            }
        }

  5. ResultMiddleware
    作用:结果中间件,可以对结构进行格式化处理、数据转换等操作。
    代码:
    public class ResultMiddleware : IMiddleware
        {
            public async Task InvokeAsync(HttpContext context, RequestDelegate next)
            {
                Console.WriteLine("result before");
                await next(context);
                Console.WriteLine("result after");
            }
        }

使用

using webapi.test.auth.Functions;
using webapi.test.auth.Middlewares;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddSingleton<IGreeter,Greeter>();
builder.Services.AddSingleton<AuthMiddleware>();
builder.Services.AddSingleton<ResourceMiddleware>();
builder.Services.AddSingleton<ActionMiddleware>();
builder.Services.AddSingleton<ExceptionMiddleware>();
builder.Services.AddSingleton<ResultMiddleware>();

var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseMiddleware<AuthMiddleware>();
app.UseMiddleware<ResourceMiddleware>();
app.UseMiddleware<ActionMiddleware>();
app.UseMiddleware<ExceptionMiddleware>();
app.UseMiddleware<ResultMiddleware>();

app.MapControllers();

app.Run();

过滤器

设计

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

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

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

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

定义

  1. ApiAuthAttribute
    作用:权控过滤器,用于认证和授权验证。
    代码:
    [AttributeUsage(AttributeTargets.Class)]
        public class ApiAuthAttribute : Attribute, IAuthorizationFilter
        {
            public void OnAuthorization(AuthorizationFilterContext context)
            {
    
            }
        }

  2. ApiResourceAttribute
    作用:资源过滤器,用于资源缓存、防盗链等。
    代码:
    [AttributeUsage(AttributeTargets.Class)]
        public class ApiResourceAttribute : Attribute, IResourceFilter
        {
            public void OnResourceExecuted(ResourceExecutedContext context)
            {
            }
    
            public void OnResourceExecuting(ResourceExecutingContext context)
            {
    
            }
        }

  3. ApiActionAttribute
    作用:方法过滤器,用于拦截每一个请求的Action方法。
    代码:
    [AttributeUsage(AttributeTargets.Class)]
        public class ApiActionAttribute : Attribute, IActionFilter
        {
            public void OnActionExecuting(ActionExecutingContext context)
            {
    
            }
            public void OnActionExecuted(ActionExecutedContext context)
            {
    
            }
        }

  4. ApiExceptionAttribute
    作用:异常过滤器,进行全局的异常信息收集和处理。
    代码:
    [AttributeUsage(AttributeTargets.Class)]
        public class ApiExceptionAttribute : Attribute, IExceptionFilter
        {
            public void OnException(ExceptionContext context)
            {
    
            }
        }

  5. ApiResultAttribute
    作用:结果过滤器,可以对结构进行格式化处理、数据转换等操作。
    代码:
    [AttributeUsage(AttributeTargets.Class)]
        public class ApiResultAtrribute : Attribute, IResultFilter
        {
            public void OnResultExecuted(ResultExecutedContext context)
            {
    
            }
    
            public void OnResultExecuting(ResultExecutingContext context)
            {
    
            }
        }

使用

    [ApiAuth]
    [ApiResource]
    [ApiAction]
    [ApiException]
    [ApiResult]
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
           //...
    }

扩展

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

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

a)两者区别
  ServiceFilter需要对自定义的Filter进行注册,TypeFilter不需要注册。
  ServiceFilter的Filter生命周期由注册时决定,TypeFilter每次都会创建一个新实例。
b)使用方式
  TypeFilter

[TypeFilter(typeof(ApiException))]
public class Test{
     //…
}

       ServiceFilter

[ServiceFilter(typeof(ApiException))]
public class Test{
    //…
}

public void ConfigureServices(IServiceCollection services){
   services.AddSingleton<ApiException>();
}

总结

通过上述内容分析得出结论,在webapi编码过程中,应该以中间件形式实现某些需要的功能,毕竟过滤器与依赖注入搭配的不是很方便,Minimal API不支持过滤器,而且过滤器已经被归类于aspnetcore.mvc命名空间下了。

测试代码:https://gitee.com/kinbor/jks.core.test.middlewareandfilter

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值