asp.net core过滤器应用

news2025/1/11 22:38:18

筛选器类型

授权筛选器

授权过滤器是过滤器管道的第一个被执行的过滤器,用于系统授权。一般不会编写自定义的授权过滤器,而是配置授权策略或编写自定义授权策略。简单举个例子。

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 这个标签的控制器
            // 过滤掉带有AllowAnonymousFilter
            if (HasAllowAnonymous(context))
            {
                return;
            }
            // 获取当前用户的信息
            var user = context.HttpContext.User;

            // 自定义的授权检查逻辑
            if (user == null || user?.Identity?.IsAuthenticated != true)
            {
                // 如果检查不通过,设置 Result 属性为一个 IActionResult 对象,可以阻止请求进一步被处理
                context.Result = new ForbidResult();
            }
        }

        // 判断是否含有IAllowAnonymous
        private 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、只能拦截JsonResult
                CommonResult 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、只能拦截JsonResult
                CommonResult 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页面筛选器
异常过滤器理解
错误处理
过滤器应用

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pixtral Large开源:Mistral AI的1240亿参数多模态模型超越GPT-4o等竞争对手

Pixtral Large是什么 Pixtral Large是由法国人工智能初创公司Mistral AI开发的超大多模态模型&#xff0c;拥有1240亿参数&#xff0c;2024年11月18日正式对外发布。它基于Mistral Large 2开发而成&#xff0c;具备1230亿参数的多模态解码器和10亿参数的视觉编码器。这个模型能…

【Diffusion分割】基于先验知识的显式-隐式扩散模型用于医学图像分割

扩散概率模型(DPM)在当前的图像生成任务中取得了无与伦比的成果,最近的一些研究工作将其应用于多个计算机视觉任务中,如图像超分辨率、物体检测等。得益于 DPM 生成细粒度细节的卓越能力,这些研究工作取得了显著的成果。在本文中,提出了一种新的基于 DPM 的生成式医学图像…

双目相机的标定,视差图,深度图,点云生成思路与实现。

该文档记录从双目相机标定到点云生成的所有过程&#xff0c;同时会附上代码。 代码直接能跑。https://github.com/stu-yzZ/stereoCamera 目录 大致思路如下&#xff1a; 一、相机标定 1、相机参数介绍 2、单目相机标定 3、双目相机标定 二、图片畸变矫正 三、极线矫正…

记录一下,解决js内存溢出npm ERR! code ELIFECYCLEnpm ERR! errno 134 以及 errno 9009

项目是个老项目&#xff0c;依赖包也比较大&#xff0c;咱就按正常流程走一遍来详细解决这个问题&#xff0c;先看一下node版本&#xff0c;我用的是nvm管理的&#xff0c;详细可以看我的其他文章 友情提醒&#xff1a;如果项目比较老&#xff0c;包又大&#xff0c;又有一些需…

秒懂:使用js验证hash, content hash , chunk hash的区别

一、使用js验证hash, content hash , chunk hash的区别 1、计算一般的 Hash&#xff08;以简单字符串为例&#xff09; 使用crypto-js库来进行哈希计算&#xff0c;需提前引入npm install crypto-js库。 crypto-js&#xff1a; 是一个JavaScript加密算法库&#xff0c;用于实…

基于MATLAB野外观测站生态气象数据处理分析实践应用

1.本课程基于MATLAB语言 2.以实践案例为主&#xff0c;提供所有代码 3.原理与操作结合 4.布置作业&#xff0c;答疑与拓展 示意图&#xff1a; 以野外观测站高频时序生态气象数据为例&#xff0c;基于MATLAB开展上机操作&#xff1a; 1.不同生态气象要素文件的数据读写与批处理…

Unity 画线(UILineRenderer)

实现 以鼠标点击点作为起点创建UILineRenderer 并记录起点。 GameObject go new GameObject(); go.transform.parent transPaint; go.transform.localPosition Vector3.zero; line go.AddComponent<UILineRenderer>(); line.LineWidth widthLine; line.color col…

D86【python 接口自动化学习】- pytest基础用法

day86 pytest配置testpaths 学习日期&#xff1a;20241202 学习目标&#xff1a;pytest基础用法 -- pytest配置testpaths 学习笔记&#xff1a; pytest配置项 主目录创建pytest.ini文件 [pytest] testpaths./testRule 然后Terminal里直接命令&#xff1a;pytest&#xff…

bash命令缓存导致命令执行失败的问题

1、问题背景 为了修复老版本 vsftpd 的安全漏洞&#xff0c;需要把生产环境上 vsftpd 版本升级到 vsftpd-3.0.5&#xff0c;因为直接使用 rpm 包的方式进行升级还涉及到下层依赖包的升级(生产环境上的依赖包版本不能随意变更&#xff0c;可能会影响其他上层应用)&#xff0c;所…

【设计模式系列】工厂方法模式(二十一)

一、什么是工厂方法模式 工厂方法模式&#xff08;Factory Method Pattern&#xff09;是一种创建型设计模式&#xff0c;其核心目的是定义一个创建对象的接口&#xff0c;但让实现这个接口的子类来决定实例化哪一个类。工厂方法模式让类的实例化推迟到子类中进行&#xff0c;…

Windows 和 Ubuntu 双系统安装

复现论文的时候&#xff0c;个别包只有Linux版本&#xff0c;并且源码编译比较麻烦&#xff0c;所以干脆直接安装一个双系统&#xff08;WinUbuntu&#xff09;&#xff0c;方便复现论文。 参考视频链接&#xff1a;Windows 和 Ubuntu 双系统的安装和卸载 0.所需工具 4G以上U…

DAY35|动态规划Part03|LeetCode:01背包问题 二维、01背包问题 一维、416. 分割等和子集

目录 01背包理论基础&#xff08;一&#xff09; 基本思路 C代码 01背包理论基础&#xff08;二&#xff09; 基本思路 C代码 LeetCode:416. 分割等和子集 基本思路 C代码 01背包理论基础&#xff08;一&#xff09; 题目链接&#xff1a;卡码网46. 携带研究材料 文字…

【SpringMVC】SpringMVC执行流程

当 Spring MVC 收到客户端的 HTTP 请求后&#xff0c;会按照以下步骤处理请求&#xff1a; 前端控制器 DispatcherServlet 接收请求&#xff1a; 客户端发送的 HTTP 请求首先被前端控制器 DispatcherServlet 拦截。DispatcherServlet 是整个流程的入口点&#xff0c;负责接收所…

flex: 1 display:flex 导致的宽度失效问题

flex: 1 & display:flex 导致的宽度失效问题 问题复现 有这样的一个业务场景&#xff0c;详情项每行三项分别占33%宽度&#xff0c;每项有label字数不固定所以宽度不固定&#xff0c;还有content 占满标签剩余宽度&#xff0c;文字过多显示省略号&#xff0c; 鼠标划入展示…

人工智能大模型培训讲师叶梓:Llama Factory 微调模型实战分享提纲

LLaMA-Factory ——一个高效、易用的大模型训练与微调平台。它支持多种预训练模型&#xff0c;并且提供了丰富的训练算法&#xff0c;包括增量预训练、多模态指令监督微调、奖励模型训练等。 LLaMA-Factory的优势在于其简单易用的界面和强大的功能。用户可以在不编写任何代码的…

基于51单片机的智能公交车报站系统GPS定位语音播报智能安全检测人数统计

功能描述 1.LCD12864可显示当前年月日&#xff0c;星期&#xff0c;时间&#xff0c; 当前站名&#xff0c;经纬度&#xff0c;是否连接GPS&#xff0c;自动/手动模式&#xff0c; 2.自带GPS定位&#xff0c;可实时显示经纬度&#xff1b; 3.通过DS1302时钟芯片&#xff0c;获…

leetcode:1995. 统计特殊四元组(python3解法)

难度&#xff1a;简单 给你一个 下标从 0 开始 的整数数组 nums &#xff0c;返回满足下述条件的 不同 四元组 (a, b, c, d) 的 数目 &#xff1a; nums[a] nums[b] nums[c] nums[d] &#xff0c;且a < b < c < d 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3…

如何把阿里云ECS里的文件下载到本地(免登录免配置)

如何把阿里云ECS里的文件下载到本地&#xff08;免登录免配置&#xff09; 作为一个阿里云ECS的用户&#xff0c;Up时长会遇到希望把ECS里的文件下载到自己的个人电脑&#xff0c;然后在自己的电脑里面查看&#xff0c;保存或者发送给别人。最近发现阿里云新上了一个功能&…

nlp培训重点

1. SGD梯度下降公式 当梯度大于0时&#xff0c;变小&#xff0c;往左边找梯度接近0的值。 当梯度小于0时&#xff0c;减去一个负数会变大&#xff0c;往右边找梯度接近0的值&#xff0c;此时梯度从负数到0上升 2.Adam优化器实现原理 #coding:utf8import torch import torch.n…

mvn test 失败,单独运行单元测试成功

标题mvn test 失败&#xff0c;单独运行单元测试成功 使用junit4进行单元测试时是通过的&#xff0c;但是在执行maven的test与package时测试不通过 报错信息&#xff1a; parse data from Nacos error,dataId:guoyu-new-asset-dev.yml,data: ....... 配置文件内容 ....... o…