WebApi过滤器初学习

news/2025/3/15 21:12:30/文章来源:https://www.cnblogs.com/guan-tou6/p/18234380

WebApi 过滤器

Authorization Filters  //权限验证
Resource Filters   //资源验证   常被用于缓存
Model Binding  //模型绑定
Action Filters  //行为   常被用于模型验证和日志记录
Exception Filters  //异常处理  常被用于错误日志
Result Filters    //结果验证  用于

三种注册方式

  • 方法注册 注册在方法上 Action
  • 类注册 注册在控制器上 Controller
  • 全局注册 注册在Program

过滤器的注解的定义

 public class CtmResourceFilterAttribute : Attribute, IResourceFilter{public void OnResourceExecuted(ResourceExecutedContext context){throw new NotImplementedException();}//控制器请求前,可以有效减少服务器的压力public void OnResourceExecuting(ResourceExecutingContext context){//可以添加短路器throw new NotImplementedException();}}
 public class CtmAuthriztionFuilterAttribute : Attribute, IAuthorizationFilter{//在请求完成前public void OnAuthorization(AuthorizationFilterContext context){throw new NotImplementedException();}}
  public class CtmActionFilterAttribute : Attribute, IActionFilter{//请求结束后public void OnActionExecuted(ActionExecutedContext context){throw new NotImplementedException();}//请求结束前public void OnActionExecuting(ActionExecutingContext context){throw new NotImplementedException();}}

三种方法权重不一样,执行的依次顺序

progarm->类注册->方法注册

相同类型的FIlter,全局注册的优先级>类上注册优先级>方法上的优先级

不同类型的拦截器互不影响,按照图例顺序

方法注册

namespace FilterDemo.Controllers
{[ApiController][Route("[controller]/[action]")]public class WeatherForecastController : ControllerBase{private readonly ILogger<WeatherForecastController> _logger;public WeatherForecastController(ILogger<WeatherForecastController> logger){_logger = logger;}[HttpGet][CtmActionFilter]//行为拦截[CtmAuthriztionFuilter]//鉴权public string Get(){return "";}}
}

类注册

namespace FilterDemo.Controllers
{[ApiController][Route("[controller]/[action]")][CtmActionFilter]//行为拦截[CtmAuthriztionFuilter]//鉴权[CtmResourceFilter]//资源拦截public class WeatherForecastController : ControllerBase{private readonly ILogger<WeatherForecastController> _logger;public WeatherForecastController(ILogger<WeatherForecastController> logger){_logger = logger;}[HttpGet]public string Get(){return "";}}
}

Progarm注册

builder.Services.AddControllers(o=>o.Filters.Add<CtmActionFilterAttribute>());
  builder.Services.AddControllers(o=> { //数字越小,越先执行o.Filters.Add<CtmActionFilterAttribute>(1);o.Filters.Add<CtmActionFilterAttribute>(2);});

过滤器的执行顺序

在方法注册上添加order比重

[HttpGet]
// [CtmActionFilter]//行为拦截
[CtmAuthriztionFuilter]//鉴权
[TypeFilter(typeof(CtmResourceFilterAttribute))]//资源拦截
[TypeFilter(typeof(CtmExceptionFilterAttriubute))]//异常处理拦截
[CtmResultFilter]
//在特性中,第一个是作为构造函数传入的,第二个是给属性传参,要把属性的名称填上
[TypeFilter(typeof(CtmActionFilterAttribute),Order =1)]
public string Get()
{return "";
}

就算是全局定义的filter,如果自行定义的order没有方法注册的比重大,那么,仍然要先执方法注册的

授权过滤器

AuthorizationFilter

过滤器管道中的第一个过滤器。

控制对操作方法的访问。

这是一个简单的模拟,目的是拿取参数中的值

短路器

前置过滤器有AuthorizationFilter和ResouceFilter,这两个过滤器是指在控制器的构造函数执行之前执行的,这两个过滤器执行后,执行构造函数,在执行Model Binding模型绑定和ActionFilter

ResourceFilter

其中Result正常来说为null,如果不等于null,正常来说,应该是短路器被触发了。

短路器被触发后,就不会去触发控制器的构造函数了,会直接通过短路器的内部逻辑返回请求。

 public class CtmResourceFilterAttribute : Attribute, IResourceFilter{private static Dictionary<string, object> _dicCache = new Dictionary<string, object>();//控制器处理请求后public void OnResourceExecuted(ResourceExecutedContext context){//获取当前访问的网址PathString path = context.HttpContext.Request.Path;//将返回的数据存在数组中_dicCache[path] = context.Result as ObjectResult;}//控制器请求前,可以有效减少服务器的压力public void OnResourceExecuting(ResourceExecutingContext context){//可以添加短路器,这里就触发短路了//context.Result = new JsonResult("没有权限");//获取当前的访问地址var path = context.HttpContext.Request.Path;//字典中是否包含pathif (_dicCache.ContainsKey(path)){//如果包含,直接返回缓存的数据context.Result = _dicCache[path] as ObjectResult;}}}

ActionFilter

用于 记录日志,模型认证

以下代码讲的是,如何用ActionFilter去记录日志和特性注入

过滤器实现构造函数注入

[HttpPost]
[TypeFilter(typeof(CtmActionFilterAttribute))]
public User AddUser(User user)
{return user;
}
 //一个特性,关于方法的拦截public class CtmActionFilterAttribute : Attribute, IActionFilter{private readonly ILogger logger;public CtmActionFilterAttribute(ILogger<CtmActionFilterAttribute> logger){this.logger = logger;}//请求结束后public void OnActionExecuted(ActionExecutedContext context){throw new NotImplementedException();}//请求结束前public void OnActionExecuting(ActionExecutingContext context){logger.LogInformation("....");}}

还有一种注册方式

 [HttpPost][ServiceFilter(typeof(CtmActionFilterAttribute))]public User AddUser(User user){return user;}

这种方式需要将filter在Progarm中进行依赖注册

builder.Services.AddTransient<CtmActionFilterAttribute>();
//这里注册的是Transient,瞬态

如果使用了ServiceFilter,那么无论是Filter本身还是filter需要注入的参数,都需要在容器中注入。

 builder.Services.AddTransient<User>();
public class CtmActionFilterAttribute : Attribute, IActionFilter
{private readonly ILogger logger;private readonly User user;public CtmActionFilterAttribute(ILogger<CtmActionFilterAttribute> logger,User user){this.logger = logger;this.user = user;}//请求结束后public void OnActionExecuted(ActionExecutedContext context){throw new NotImplementedException();}//请求结束前public void OnActionExecuting(ActionExecutingContext context){PathString path = context.HttpContext.Request.Path;var argumnet = context.ActionArguments;if (argumnet.ContainsKey("User")){var user = argumnet["user"] as User;logger.LogInformation($"{user.Name} is visiting {path}");}else{logger.LogInformation($"{user.Name} is visiting {path}");}}

利用缓存实现短路

缓存使用menory catch

首先要对menory catch进行注册

注意注册时,不能用瞬态,使用单例模式,保持缓存的存在

builder.Services.AddSingleton<IMemoryCache,MemoryCache>();

对控制器使用

        [HttpGet]// [CtmActionFilter]//行为拦截[CtmAuthriztionFuilter]//鉴权[TypeFilter(typeof(CtmResourceFilterAttribute))]//资源拦截public string Get(){return "";}

这样才能在ResourceFilterAttribute中拿到相应的缓存

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;namespace FilterDemo.Filters
{public class CtmResourceFilterAttribute : Attribute, IResourceFilter{private static Dictionary<string, object> _dicCache = new Dictionary<string, object>();private readonly IMemoryCache memoryCache;//控制器处理请求后public CtmResourceFilterAttribute(IMemoryCache memoryCache){this.memoryCache = memoryCache;}public void OnResourceExecuted(ResourceExecutedContext context){/* //获取当前访问的网址PathString path = context.HttpContext.Request.Path;//将返回的数据存在数组中_dicCache[path] = context.Result as ObjectResult;*///获取当前访问的网址PathString path = context.HttpContext.Request.Path;//不再用字典,用缓存进行存储返回的结果//两个参数,一个key一个valuememoryCache.Set(path, context.Result as ObjectResult); }//控制器请求前,可以有效减少服务器的压力public void OnResourceExecuting(ResourceExecutingContext context){//可以添加短路器,这里就触发短路了//context.Result = new JsonResult("没有权限");//获取当前的访问地址var path = context.HttpContext.Request.Path;//字典中是否包含path/* if (_dicCache.ContainsKey(path)){//如果包含,直接返回缓存的数据context.Result = _dicCache[path] as ObjectResult;}*///从缓存中拿到当前path对应的值//有值返回true,没有值返回falseif(memoryCache.TryGetValue(path,out object value)){context.Result = value as ObjectResult;}}}
}

关于out

  if(memoryCache.TryGetValue(path,out object value)){context.Result = value as ObjectResult;}

解析版

 object value;if(memoryCache.TryGetValue(path,out value)){context.Result = value as ObjectResult;}

给参数赋值后,加上out,可以将返回值,和加上out修饰的值一并带出来。

ExceptionFilters

异常处理拦截

作用是捕获异常的处理

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterDemo.Filters
{public class CtmExceptionFilterAttriubute : Attribute, IExceptionFilter{private readonly ILogger<CtmExceptionFilterAttriubute> logger;public CtmExceptionFilterAttriubute(ILogger<CtmExceptionFilterAttriubute> logger){this.logger = logger;}//在这里可以拿到错误信息public void OnException(ExceptionContext context){logger.LogInformation(context.Exception.Message);context.Result = new ContentResult{Content = context.Exception.Message};}}
}
 [HttpGet]// [CtmActionFilter]//行为拦截[CtmAuthriztionFuilter]//鉴权[TypeFilter(typeof(CtmResourceFilterAttribute))]//资源拦截[TypeFilter(typeof(CtmExceptionFilterAttriubute))]//异常处理拦截public string Get(){return "";}

异常过滤器的捕获范围

可以用于常见的错误处理策略

非常适合捕获发生在操作中的异常

建议使用中间件的处理异常

基于所调用的操作方法,仅当错误处理不同时,才使用异常过滤器。

只能捕获跟action相关的异常,只能捕获操作相关的异常

捕获范围很小

ResultFilters

结果过滤器,围绕着操作结果执行。

只有当操作能够生成结果时,才会使用结果过滤器。

在异常过滤器通过生成操作结果时,结果过滤器不会执行。

结果过滤器中的异常不会被异常过滤器捕获

但是如果继承了IAlwaysRunResultFilter接口,那么就可以在异常过滤器捕获异常后仍然可以进入结果过滤器

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterDemo.Filters
{public class CtmAlwaysResultFilter : Attribute, IAlwaysRunResultFilter{public void OnResultExecuted(ResultExecutedContext context){throw new NotImplementedException();}public void OnResultExecuting(ResultExecutingContext context){if (context.Result is StatusCodeResult statusCodeResult&& statusCodeResult.StatusCode == StatusCodes.Status404NotFound){context.Result = new ObjectResult("这是404"){StatusCode = StatusCodes.Status404NotFound};}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/720803.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跨越云端,华为云技术专家分享高效跨云迁移实践

跨云场景两端云平台的管理是相对割裂的,这也导致虚拟机的跨云迁移无法像云内热迁移一样无中断,需要通过和云平台解耦的迁移工具来实现。本文分享自华为云社区《【华为云Stack】【大架光临】第18期:跨越云端,华为云Stack的高效跨云迁移实践》,作者: 大架光临。1 背景 在企…

强!推荐一款开源接口自动化测试平台:AutoMeter-API !

在当今软件开发的快速迭代中,接口自动化测试已成为确保代码质量和服务稳定性的关键步骤。 随着微服务架构和分布式系统的广泛应用,对接口自动化测试平台的需求也日益增长。 今天,我将为大家推荐一款强大的开源接口自动化测试平台: AutoMeter-API。 1、介绍 AutoMeter-API是一…

flutter3-weos手机OS系统|Flutter3.22+Getx仿ios桌面管理OA应用

原创自研flutter3.x+getx仿制ios手机桌面UI管理系统模板Flutter3-OS。 flutter3-osx基于最新跨平台技术Flutter3.22+Dart3.4+GetX+fl_chart实战仿IOS风格手机os管理系统。全新自研flutter磁贴式栅格布局引擎、分屏式多页管理、自定义主题壁纸、卡片式桌面小部件、可拖拽式悬浮球…

qt 操作sqlite数据库

添加密码:要有圈住的这一句 原文连接

第二次大作业Blog

目录前言设计与分析踩坑心得改进建议总结 前言知识点:类与对象的应用: 在三次大作业中,类与对象的应用无疑是核心和基础。这充分体现了Java作为一种面向对象编程语言的特性。通过定义类,我们可以创建具有特定属性和行为的对象,从而构建出复杂的程序逻辑。在每次大作业中,…

C#.Net筑基-String字符串超全总结 [深度好文]

字符串是日常编码中最常用的引用类型了,可能没有之一,加上字符串的不可变性、驻留性,很容易产生性能问题,因此必须全面了解一下。字符串是日常编码中最常用的引用类型了,可能没有之一,加上字符串的不可变性、驻留性,很容易产生性能问题,因此必须全面了解一下。01、字符…

类的继承,接口的使用

1-知识点,题量,难度总结 1.this与super的区分与使用,如何正确使用多态(用父类类型创建子类对象,并调用子类中重写父类中的抽象方法)(在大作业5中的第二道修改学生信息中)(第三道中父类向下转型,另外还有子类向上转型)。 2接口的使用,多态的具体体现(例如在第一次家…

The University of Sydney

QS大学排名QS世界大学排名 QS大学学科排名 QS亚洲大学排名 QS商科硕士排名 QS就业竞争力排名 QS全球MBA排名软科ARWU大学排名 泰晤士大学排名 USNEWS大学排名 金融时报(FT)商学院排名 EduRank大学排名 CWUR世界大学排名 武书连大学排名 校友会大学排名 登录 去除广告?下载大…

QS世界大学排名 2025

大学排名 发现 展会活动 留学准备 申请 职业发展中文免费注册排名方法什么是QS之星? QS世界大学排名 2025通过2025年的QS世界大学排名,发现世界顶尖大学。展开In partnership with 排名榜单 排名指标 年份 2025…

chrome浏览器被360导航劫持解决办法

右键单击桌面浏览器图标 点击属性 修改目标,去点360的导航url,ok

读AI未来进行式笔记04数字医疗与机器人

读AI未来进行式笔记04数字医疗与机器人1. 数字医疗 1.1. 20世纪的“现代医学”得益于史无前例的科学突破,使得医疗的方方面面都得到改善,让人类预期寿命从1900年的31岁提高到2017年的72岁 1.2. 现有的医疗数据库和流程将实现数字化 1.2.1. 患…

linux启动

1. BIOS BIOS 代表基本输入/输出系统。简单来说,BIOS 会加载并执行主引导记录 (MBR) 引导加载程序。 首次打开计算机时,BIOS 首先对 HDD 或 SSD 执行一些完整性检查。 然后,BIOS 搜索、加载并执行引导加载程序,该程序可以在主引导记录 (MBR) 中找到。MBR 有时位于 USB 记忆…