asp.net core过滤器应用
筛选器类型
授权筛选器
授权过滤器是过滤器管道的第一个被执行的过滤器,用于系统授权。一般不会编写自定义的授权过滤器,而是配置授权策略或编写自定义授权策略。简单举个例子。
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterStudy01.Filter
{/// <summary>/// 授权过滤器/// builder.Services.AddMvc(options =>{options.Filters.Add(new WjAuthorizationlFilter());});/// [TypeFilter(typeof(WjAuthorizationlFilter))]可以加在类或者控制器上/// 不登陆的情况下访问/Admin/Index/// </summary>public class WjAuthorizationlFilter : IAuthorizationFilter{public void OnAuthorization(AuthorizationFilterContext context){// 需要排除具有AllowAnymons 这个标签的控制器// 过滤掉带有AllowAnonymousFilterif (HasAllowAnonymous(context)){return;}// 获取当前用户的信息var user = context.HttpContext.User;// 自定义的授权检查逻辑if (user == null || user?.Identity?.IsAuthenticated != true){// 如果检查不通过,设置 Result 属性为一个 IActionResult 对象,可以阻止请求进一步被处理context.Result = new ForbidResult();}}// 判断是否含有IAllowAnonymousprivate bool HasAllowAnonymous(AuthorizationFilterContext context){if (context.Filters.Any(filter => filter is IAllowAnonymousFilter)){return true;}// 终节点:里面包含了路由方法的所有元素信息(特性等信息)var endpoint = context.HttpContext.GetEndpoint();return endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null;}}
}
https://zhuanlan.zhihu.com/p/677748480
https://blog.csdn.net/qq_41942413/article/details/135163599
https://learn.microsoft.com/zh-cn/aspnet/core/security/authorization/simple?view=aspnetcore-9.0
IP过滤器,不过这个可以放到Action过滤器中,看需求,如果全部限制可以放授权筛选器,也可以简单的做个ip黑名单和白名单
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterStudy01.Filter
{/// <summary>/// 实现ip过滤器/// </summary>public class WjlIpAuthorizationFilter : IAuthorizationFilter{public void OnAuthorization(AuthorizationFilterContext context){var allowIps = new List<string>(){"127.0.0.1"};var requestIp = context?.HttpContext?.Connection?.RemoteIpAddress?.ToString() ?? "";if (!allowIps.Contains(requestIp)){var result = new{Success = false,Msg = "非法请求"};if (context != null){context.Result = new JsonResult(result);}}}}
}
资源筛选器
资源过滤器,在授权过滤器执行后执行,该过滤器包含“之前”和“之后”两个行为,包裹了模型绑定、操作过滤器、Action执行、异常过滤器、结果过滤器以及结果执行。
缓存结果提高网站的响应速度,缓存后,就可以直接从内存中直接取数据,而无需在执行方法。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterStudy01.Filter
{/// <summary>/// 资源过滤器实现缓存/// IAsyncResourceFilter/// 如果继承Attribute 使用方式如下[WjlResouerceFilter]/// 如何不继承 builder.Services.AddMvc(options =>{options.Filters.Add(new WjlResouerceFilter());});/// </summary>public class WjlResouerceFilterAttribute : Attribute, IResourceFilter{private static readonly Dictionary<string, IActionResult?> dic = new Dictionary<string, IActionResult?>();/// <summary>/// 方法执行之后/// </summary>/// <param name="context"></param>public void OnResourceExecuted(ResourceExecutedContext context){var path = context.HttpContext.Request.Path;dic[path] = context?.Result;}/// <summary>/// 方法执行之前/// </summary>/// <param name="context"></param>public void OnResourceExecuting(ResourceExecutingContext context){var path = context.HttpContext.Request.Path;if (dic.ContainsKey(path)){context.Result = dic[path];}}}
}
操作筛选器
操作过滤器,在模型绑定后执行,该过滤器同样包含“之前”和“之后”两个行为,包裹了Action的执行(不包含Controller的创建)。如果Action执行过程中或后续操作过滤器中抛出异常,首先捕获到异常的是操作过滤器的OnActionExecuted,而不是异常过滤器。
案例:接口访问日志记录,完整的日志记录方便跟踪分析问题以及攻击
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using System.Diagnostics;
using System.Dynamic;
using System.Text;
using System.Text.Json;namespace FilterStudy01.Filter
{/// <summary>/// 操作过滤器/// builder.Services.AddMvc(options =>{options.Filters.Add(new WjlAsyncActionFilter());});/// </summary>public class WjlAsyncActionFilter : IAsyncActionFilter{/// <summary>/// 记录请求日志,方便跟踪以及预警/// 需要开启Buffer/// app.Use(next => new RequestDelegate(async context => {context.Request.EnableBuffering();await next(context);}));/// </summary>/// <param name="context"></param>/// <param name="next"></param>/// <returns></returns>public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next){dynamic model = new ExpandoObject();var httpContext = context.HttpContext;var name = context.ActionDescriptor.DisplayName;var actionName = context.ActionDescriptor.RouteValues["action"] ?? ""; //action名字var controllerName = context.ActionDescriptor.RouteValues["controller"] ?? ""; //controller名字var queryStrings = httpContext.Request.QueryString; //GET请求的后缀var fromString = new StringBuilder();if (httpContext.Request.HasFormContentType){var forms = httpContext.Request?.Form; //Form表单请求if (forms != null){foreach (var item in forms){fromString.Append($"{item.Key}={item.Value}");}}}var ipAddress = httpContext?.Connection?.RemoteIpAddress?.ToString();string body = "";StringValues authHeader = "";if (httpContext != null && httpContext.Request != null){if (httpContext.Request.Body != null){httpContext.Request.Body.Position = 0;//读取请求体var sr = new System.IO.StreamReader(httpContext.Request.Body);body = await sr.ReadToEndAsync(); //请求体内容httpContext.Request.Body.Position = 0;}httpContext.Request.Headers.TryGetValue("Authorization", out authHeader);}//赋值model.Headers = authHeader;model.RequestBody = body;model.IPAddress = ipAddress;model.Result = "";model.FormString = fromString.ToString();model.QueryString = queryStrings;model.Action = actionName;model.ActionClassName = name;model.Controller = controllerName;var stopWatch = Stopwatch.StartNew();stopWatch.Reset();await next();stopWatch.Stop();var customerTime = Math.Round(stopWatch?.Elapsed.TotalMilliseconds ?? 0, 2);//ObjectResult、JsonResult、ViewResult、LocalRedirectResult//RedirectResult、RedirectToActionResult、BadRequestResult、BadRequestObjectResult//OkResult OkObjectResult NoContentResult NotFoundResult ForbiddenResult//ChallengeResult StatusCodeResult ObjectResult FileResult(FileContentResult、FilePathResult、FileStreamResult、VirtualFileResult)//ContentResult EmptyResult ActionResult(基类不能直接用)//上面是全部的类型按照需要自己处理var fileresult = context.Result as FileResult;if (fileresult == null){var result = context.Result as ObjectResult;var resValue = result?.Value;if (result != null && resValue != null){model.Result = JsonSerializer.Serialize(resValue);}}else{model.Result = "文件下载";}Console.WriteLine(JsonSerializer.Serialize(model));}}
}
异常筛选器
监听全局异常并统一格式返回
using FilterStudy01.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Text;namespace FilterStudy01.Filter
{/// <summary>/// 使用/// builder.Services.AddMvc(options =>{options.Filters.Add(new WjlExceptionFilter());});/// 并不是所有的异常都捕获,比如mvc中razor页面报错不能捕获/// 可以捕获Controller创建时(也就是只捕获构造函数中抛出的异常)、模型绑定、Action Filter和Action中抛出的未处理异常/// 其他异常不会捕获,可以使用中间件/// </summary>public class WjlExceptionFilter : IAsyncExceptionFilter{/// <summary>/// 获取异常的详细信息/// </summary>/// <param name="ex"></param>/// <returns></returns>private string GetExceptionDetails(Exception ex){if (ex == null){return string.Empty;}StringBuilder sb = new StringBuilder();sb.Append("异常消息: ");sb.Append(ex.Message);sb.Append("\n");sb.Append("堆栈跟踪: ");sb.Append(ex.StackTrace);// 递归获取内部异常的详细信息 if (ex.InnerException != null){sb.Append(GetExceptionDetails(ex.InnerException));}return sb.ToString();}/// <summary>/// 出现异常时触发/// </summary>/// <param name="context"></param>/// <returns></returns>public async Task OnExceptionAsync(ExceptionContext context){// 如果异常没有被处理则进行处理if (context.ExceptionHandled == false){var httpContext = context.HttpContext;//action名字var actionName = context.ActionDescriptor.RouteValues["action"] ?? "";//controller名字var controllerName =context.ActionDescriptor.RouteValues["controller"] ?? "";var path = httpContext.Request.Path;//这里要替换成日志Console.WriteLine(GetExceptionDetails(context.Exception));CommonResult commonResult = new CommonResult();commonResult.ResultNo = 1;commonResult.ResultData = "server error";context.Result = new JsonResult(commonResult);}// 设置为true,表示异常已经被处理了context.ExceptionHandled = true;}}
}using FilterStudy01.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Text;namespace FilterStudy01.Filter
{/// <summary>/// 局部使用/// [WjlExceptionFilter]/// </summary>public class WjlExceptionFilterAttribute : ExceptionFilterAttribute{/// <summary>/// 获取异常的详细信息/// </summary>/// <param name="ex"></param>/// <returns></returns>private string GetExceptionDetails(Exception ex){if (ex == null){return string.Empty;}StringBuilder sb = new StringBuilder();sb.Append("异常消息: ");sb.Append(ex.Message);sb.Append("\n");sb.Append("堆栈跟踪: ");sb.Append(ex.StackTrace);// 递归获取内部异常的详细信息 if (ex.InnerException != null){sb.Append(GetExceptionDetails(ex.InnerException));}return sb.ToString();}public override async Task OnExceptionAsync(ExceptionContext context){// 如果异常没有被处理则进行处理if (context.ExceptionHandled == false){var httpContext = context.HttpContext;//action名字var actionName = context.ActionDescriptor.RouteValues["action"] ?? "";//controller名字var controllerName =context.ActionDescriptor.RouteValues["controller"] ?? "";var path = httpContext.Request.Path;//这里要替换成日志Console.WriteLine(GetExceptionDetails(context.Exception));CommonResult commonResult = new CommonResult();commonResult.ResultNo = 1;commonResult.ResultData = "服务器开小差了";context.Result = new JsonResult(commonResult);}// 设置为true,表示异常已经被处理了context.ExceptionHandled = true;}}
}
结果筛选器
对返回的结果封装,统一结果返回
using FilterStudy01.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterStudy01.Filter
{/// <summary>/// 全局使用/// </summary>public class WjlResultFilter : IResultFilter{/*使用builder.Services.AddMvc(options =>{options.Filters.Add(new WjlResultFilter());});*/public void OnResultExecuted(ResultExecutedContext context){}public void OnResultExecuting(ResultExecutingContext context){//ObjectResult、JsonResult、ViewResult、LocalRedirectResult//RedirectResult、RedirectToActionResult、BadRequestResult、BadRequestObjectResult//OkResult OkObjectResult NoContentResult NotFoundResult ForbiddenResult//ChallengeResult StatusCodeResult ObjectResult FileResult(FileContentResult、FilePathResult、FileStreamResult、VirtualFileResult)//ContentResult EmptyResult ActionResult(基类不能直接用)var jsonResult = context.Result as JsonResult;if (jsonResult != null && jsonResult.Value != null){//1、只能拦截JsonResultCommonResult commonResult = new CommonResult();commonResult.ResultNo = 0;commonResult.ResultData = jsonResult.Value;jsonResult.Value = commonResult;}}}
}using FilterStudy01.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;namespace FilterStudy01.Filter
{/// <summary>/// 局部使用/// </summary>public class WjlResultFilterAttribute : ResultFilterAttribute{public override void OnResultExecuting(ResultExecutingContext context){var jsonResult = context.Result as JsonResult;if (jsonResult != null && jsonResult.Value != null){//1、只能拦截JsonResultCommonResult commonResult = new CommonResult();commonResult.ResultNo = 0;commonResult.ResultData = jsonResult.Value;jsonResult.Value = commonResult;}}}
}
筛选器接口的同步和异步版本任意实现一个,而不是同时实现 。 运行时会先查看筛选器是否实现了异步接口,如果是,则调用该接口。 如果不是,则调用同步接口的方法。 如果在一个类中同时实现异步和同步接口,则仅调用异步方法。 使用抽象类(如 ActionFilterAttribute)时,将为每种筛选器类型仅重写同步方法或仅重写异步方法。
大佬总结的图示
参考
授权过滤器
https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-8.0
https://blog.csdn.net/sD7O95O/article/details/119223675
Razor页面筛选器
异常过滤器理解
错误处理
过滤器应用
相关文章:

asp.net core过滤器应用
筛选器类型 授权筛选器 授权过滤器是过滤器管道的第一个被执行的过滤器,用于系统授权。一般不会编写自定义的授权过滤器,而是配置授权策略或编写自定义授权策略。简单举个例子。 using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCo…...
力扣面试题 31 - 特定深度节点链表 C语言解法
题目: 给定一棵二叉树,设计一个算法,创建含有某一深度上所有节点的链表(比如,若一棵树的深度为 D,则会创建出 D 个链表)。返回一个包含所有深度的链表的数组。 示例: 输入…...
WordPress阅读文章显示太慢的处理
有两种方式, 1. 完全静态化。 动态都变成html,不再查数据库就快了。 但尝试了几个插件,都未成功。算了后面再研究。 2. cache缓存 用了WP Super Cache测试了一下,打开过一次后,文章秒开,也算达到了要求…...
关于多个线程共享一个实例对象
在多线程环境中,多个线程可能同时调用同一个对象的实例方法,这时候需要考虑如何保证线程安全。理解不同场景下的线程安全性是至关重要的,特别是当方法涉及共享状态时。 1. 共享实例与方法执行 共享实例:多个线程共享同一个实例对…...

【C++】printf 函数详解与格式化输出控制
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯printf 基础用法1.1 printf 的常见占位符1.2 占位符与参数的对应关系1.3 换行控制示例: 💯格式化输出控制2.1 输出宽度控制2.1.1 指定最小宽度 2.2 …...
HDFS 操作命令
在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在 集群上的文件系统称为 分布式文件系统 。 HDFS ( Hadoop Distributed File System )是 Apache Hadoop 项目的一个子项目, Hadoo…...
html ul li 首页渲染多条数据 但只展示八条,其余的数据全部隐藏,通过icon图标 进行展示
<div style"float: left;" id"showMore"> 展开 </div> <div style"float: left;“id"hideLess"> 收起 </div> var data document.querySelectorAll(.allbox .item h3 a); const list document.querySelectorAl…...

Facebook:筑牢隐私安全堡垒,守护社交净土
在全球社交媒体平台中,Facebook一直是风靡全球的佼佼者。然而,随着数字化信息的迅速膨胀,用户隐私保护的重要性日益凸显。面对用户对数据安全性的高度重视,Facebook致力于通过一系列措施来确保隐私保护,守护每位用户的…...
2024年构建PHP应用开发环境
文章目录 前言选择合适的PHP版本安装与配置PHP环境Windows平台Linux平台macOS平台 集成Web服务器数据库连接与管理使用Composer进行依赖管理调试工具的选择代码质量管理部署与持续集成安全性考虑参考资料结语 前言 随着互联网的发展,PHP作为一门成熟的服务器端编程…...
Apache Commons Chain 与 Spring Boot 整合:构建用户注册处理链
文章目录 概述1. 环境准备2. 创建自定义上下文3. 创建命令验证用户输入保存用户数据发送欢迎邮件 4. 构建并执行处理链5. 使用处理链6. 运行结果7. 总结 概述 本文档旨在展示如何在 Spring Boot 应用中使用 Apache Commons Chain 来实现一个用户注册的处理链。我们将通过 Chai…...

一、测试工具LoadRunner Professional脚本编写-录制前设置
设置基于URL的脚本 原因:基于HTML的脚本会导致login接口不能正确录制 设置UTF-8 原因:不勾选此项会导致脚本中文变为乱码...
React Native 组件详解之SectionList、StatusBar、Switch、Text 、 TextInput
在本文中,我们将详细介绍 React Native 中的五个常用组件:SectionList、StatusBar、Switch、Text 和 TextInput。每个组件都有其独特的用途和特性,我们将通过示例代码和 API 说明来帮助你更好地理解和使用它们。 SectionList SectionList 是…...
阿里云:aliyun-cli和ali-instance-cli
概念: 这篇文章只是来澄清一下这俩“cli"之间的区别和联系: aliyun cli 和 ali-instance-cli 都是阿里云提供的命令行工具,但它们的功能和使用场景有所不同。 1. aliyun cli 是一个通用的阿里云命令行接口工具,它允许用户…...

Linux 远程连接服务
远程连接服务器简介 什么是远程连接服务器 远程连接服务器通过文字或图形接口方式来远程登录系统,让你在远程终端前登录linux主机以取得可操 作主机接口(shell),而登录后的操作感觉就像是坐在系统前面一样。 远程连接服务器的功…...
Docker 安装和使用
#Docker 安装和使用 文章目录 1. 安装2. 干掉讨厌的 sudo3. 使用镜像源3.1. 使用 upstart 的系统3.2. 使用 systemd 的系统 4. 基本使用4.1. 容器操作4.2. 镜像操作 5. 网络模式说明5.1. bridge 模式5.2. host 模式5.3. container 模式5.4. none 模式 6. 查看 Docker run 启动参…...

web基础和http协议 附:nginx服务的安装
web基础和http协议: https://www.baidu.com/ URL https:// 协议 http:// www.baidu.com/ 域名 web介绍: DNS和域名 DNS解析的方式: 1、运营商 2、/etc/hosts 人工配置的域名和ip地址之间的映射关系 3、/etc/resolv.conf dns服务器的ip地址 bind,内网解析域名和ip地址…...

springboot利用easypoi实现简单导出Excel
vue springboot利用easypoi实现简单导出 前言一、easypoi是什么?二、使用步骤 1.传送门2.前端vue3.后端springboot 3.1编写实体类(我这里是dto,也一样)3.2控制层结尾 前言 今天玩了一下springboot利用easypoi实现excel的导出,以前…...

【前端新手小白】学习Javascript的【开源好项目】推荐
目录 前言 1 项目介绍 1.1 时间日期类 1.2 网页store类 1.3 事件类 1.4 Number类 1.5 String类 1.6 正则验证类 1.7 ajax类 1.8 data数据类 1.9 browser浏览器类 2 学习js-tool-big-box开源项目时有哪些收获 2.1 你可以这样做 2.2 如果你需要使用本项目 2.3 你…...

CentOS7虚拟机 网络适配器 NAT模式和桥接模式区别
一、环境介绍 宿主机:Windows电脑 虚拟机:VMware下的CentOS7 局域网:路由器下的各真实主机组成的网络 内部局域网:宿主机构建的一个内部网路 二、NAT和桥接网络链接模式区别 NAT模式:相当于宿主机构建一个内部局域网&a…...

sql删除冗余数据
工作或面试中经常能遇见一种场景题:删除冗余的数据,以下是举例介绍相应的解决办法。 举例: 表结构: 解法1:子查询 获取相同数据中id更小的数据项,再将id不属于其中的数据删除。-- 注意:mysql中…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...