过滤器,从我们开始开发 Asp.Net 应用程序开始,就一直伴随在我们左右;Asp.Net Core 提供多种类型的过滤器,以满足多种多样的业务应用场景;并且在 Asp.Net Core 本身,过滤器的应用也非常广泛;但是,在实际的业务场景中,大部分开发人员只使用到其中 1 到 2 种类型,当然,这其中大部分可能性是由于业务场景的适用性使然,本文尝试简单介绍 Asp.Net Core 中提供的各种过滤器,以及实际的应用场景,希望对您有所帮助。
1. 介绍 1.1 作用范围过滤器的作用范围
每种不同的过滤器都有实际的作用范围,有一些全局过滤器还有作用域的限制,这取决于应用开发者在定义和初始化过滤器的时候的选择,每个过滤器本身处理任务的权限和功能都大不相同,但是他们都有一个共同点,就是通过特性标记的方式使用,比如以下代码,对一个 Action 使用了过滤器 CustomerActionFilter
原理解释
过滤器一般在 Asp.Net Core MVC 管道内运行,一般在操作执行之前(befor) 或者执行之后(after) 执行,以供开发者可以选择在不同的执行阶段介入处理
类型介绍
上图既是 Asp.Net Core 内置的各种过滤器类型,也是其执行优先级顺序,相同类型的过滤器还可以定义在某个阶段执行的顺序
授权过滤器 AuthorizeAttribute
资源过滤器 IResourceFilter
异常过滤器 IExceptionFilter
操作过滤器 ActionFilterAttribute
结果过滤器 IResultFilter
3. 授权过滤器3.1 使用介绍
在请求到达的时候最先执行,优先级最高,主要作用是提供用户请求权限过滤,对不满足权限的用户,可以在过滤器内执行拒绝操作,俗称“管道短路”
*注意:该过滤器只有执行之前(befor),没有执行之后(after)的方法
通常情况下,不需要自行编写过滤器,因为该过滤器在 Asp.Net Core 内部已经有了默认实现,我们需要做的就是配置授权策略或者实现自己的授权策略,然后由系统内置的授权过滤器调用授权策略即可
必须将该过滤器内部可能出现的异常全部处理,因为在授权过滤器之前,没有任何组件能够捕获授权过滤器的异常,一旦授权管理器内部发生异常,该异常将直接输出到结果中
3.2 应用场景
授权管理器 AuthorizeAttribute 位于 命名空间 Microsoft.AspNetCore.Authorization 内,使用方式非常简单,查看以下代码
[Authorize] [Route("api/[controller]")] public class UserController : Controller { [AllowAnonymous] [HttpGet] public ActionResult<string> Get() { return "default"; } [HttpPost] public ActionResult<string> Post() { return "default"; } }UserController 被应用了 Authorize 特性进行标记,表示对该控制器内的任意操作执行授权验证;但是单独对 Get 操作进行了授权通过对标记,即 AllowAnonymous ,表示允许匿名访问
这是非常常用的做法,在授权应用中,常常需要对部分操作进行单独的授权策略
关于授权过滤器,先介绍到这里,下一篇单独对授权过滤器进行演示,因为关于这块的内容,要讲的实在是太多了
但请求进入,通过授权过滤器后,接下来将执行资源过滤器(如果有定义),使用资源过滤器甚至可以改变绑定模型,还可以在资源过滤器中实现缓存以提高性能
4.1 资源管理器实现自接口 IResourceFilter 或者 IAsyncResourceFilter,现在我们来实现一个资源过滤器,输出一行信息,看看执行顺序
public class CustomerResourceFilter : Attribute, IResourceFilter { public void OnResourceExecuted(ResourceExecutedContext context) { Console.WriteLine("==== OnResourceExecuted"); } public void OnResourceExecuting(ResourceExecutingContext context) { Console.WriteLine("==== OnResourceExecuting"); } }4.2 对 HomeController 的操作应用该资源过滤器,看看对一个操作同时应用 CustomerActionFilter 和 CustomerResourceFilter ,他们的执行顺序是什么
[Route("api/[controller]")] [ApiController] public class HomeController : ControllerBase { [HttpGet] [CustomerActionFilter] [CustomerResourceFilter] public async Task<ActionResult<IEnumerable<string>>> Get() { return new string[] { "value1", "value2" }; } }4.3 启动程序,访问 :5000/api/home,输出结果如下