DotNet6中的过滤器

在 .NET 中配置过滤器(Filter)涉及在 ASP.NET Core MVC 或 Web API 应用程序中使用过滤器来处理 HTTP 请求的前置和后置条件。过滤器可以在控制器执行前后以及操作执行前后执行。常见的过滤器类型包括认证过滤器、授权过滤器、资源过滤器、操作过滤器和异常过滤器。

1、认证过滤器

认证过滤器(Authentication Filter)在 ASP.NET Core 中负责对用户的身份进行验证,确保请求来自经过身份验证的用户。它是过滤器管道中的第一个步骤,用来判断请求的来源是否有效。通常,认证过滤器会检查请求中的身份凭证(例如令牌、Cookie 等),并基于此确定用户的身份。

认证过滤器的作用

认证过滤器的主要职责是:

  1. 验证用户身份:确定请求是否包含有效的身份凭证,如 JWT(JSON Web Token)、OAuth 令牌、API 密钥、Session Cookie 等。
  2. 为请求上下文添加用户信息:如果认证成功,认证过滤器将用户信息(如用户身份 ClaimsPrincipal)添加到请求上下文(HttpContext.User)中,这样后续的过滤器和控制器可以使用该信息。
  3. 拒绝未认证的请求:如果请求没有包含有效的身份凭证,认证过滤器可以阻止请求进入控制器,并直接返回未授权的响应(如 401 Unauthorized)。

认证过滤器与其他过滤器的关系

认证过滤器是过滤器管道中的第一个过滤器,它在授权过滤器(Authorization Filters)之前执行:

  1. 认证过滤器:检查用户是否经过身份验证。
  2. 授权过滤器:在身份验证成功的基础上,进一步检查用户是否有访问资源的权限。

举例来说,认证过滤器会确保用户已经登录,授权过滤器则会检查该用户是否具有访问某个资源的权限。

/// <summary>
/// 自定义权限过滤器
/// </summary>
public class CustomAuthorityFilter : Attribute, IAuthorizationFilter
{
    /// <summary>
    /// 通过依赖注入的方式传递数据
    /// </summary>
    public ISharedDataService sharedDataService;
    public CustomAuthorityFilter(ISharedDataService sharedDataService)
    {
        this.sharedDataService = sharedDataService;
    }
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        //假设简单的进行 API 密钥认证
        var apiKey=context.HttpContext.Request.Headers["ApiKey"].FirstOrDefault();
        if (apiKey==null||apiKey!= "valid-api-key")
        {
            //如果API密钥不正确,返回401
            context.Result=new UnauthorizedResult();
        }

        //使用依赖注入的方式传递数据
        sharedDataService.Data="这是我的数据";
        //使用HttpContext.Items 给控制器传递数据
        context.HttpContext.Items["MyData"]= "这是我的数据";
        //使用ControllerContext.RouteData.Values给控制器传递数据
        context.RouteData.Values["MyData"] = "这是我的数据";
    }
}

为什么认证一般由中间件处理?

ASP.NET Core 中的认证通常通过中间件而不是过滤器来处理,因为认证涉及到整个应用的请求生命周期。例如,JWT 令牌或 Cookie 通常会在请求到达控制器之前就被解析,并将用户信息添加到 HttpContext.User 中。通过中间件实现,可以确保所有请求都经过身份验证,而不必依赖控制器或过滤器的存在。

2、授权过滤器

public class CustomAuthorizationFilter : IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;
        
        // 如果用户未认证,返回 401 未授权
        if (!user.Identity.IsAuthenticated)
        {
            context.Result = new UnauthorizedResult();
            return;
        }

        // 如果用户不具有某个特定声明,返回 403 禁止访问
        if (!user.HasClaim(c => c.Type == "Permission" && c.Value == "CanAccess"))
        {
            context.Result = new ForbidResult();
        }
    }
}

3、资源过滤器

资源过滤器(Resource Filters)在 ASP.NET Core 中是用来在模型绑定之前或操作结果之后进行处理的过滤器。它们可以用来实现一些前置和后置处理逻辑,比如缓存处理、资源管理、以及请求数据的预处理等。

用途

资源过滤器通常用于以下几个方面:

  1. 缓存控制:在执行主要的操作逻辑之前,检查是否有缓存的结果可以直接返回,从而避免不必要的数据库查询或复杂计算。
  2. 资源的初始化和释放:确保在请求处理的前后分配和释放必要的资源,例如数据库连接、文件句柄等。
  3. 请求数据的预处理:在模型绑定之前对请求数据进行预处理或验证。
  4. 响应的后处理:在发送响应到客户端之前进行最后的数据修改或格式化。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace AopDemo.Filter
{
    /// <summary>
    /// 定义一个自定义的资源过滤器
    /// </summary>
    public class CustomResourceFilter : Attribute, IResourceFilter
    {
        //定义一个缓存字典
        private static readonly Dictionary<string, object> Cache = new Dictionary<string, object>();
        private static string CacheKey;
        void IResourceFilter.OnResourceExecuting(ResourceExecutingContext context)
        {
            CacheKey = context.HttpContext.Request.Path.Value;
            //检查缓存中是否存在数据
            if (Cache.TryGetValue(CacheKey, out var cacheValue))
            {
                //如果存在数存在,直接返回
                context.Result = new ObjectResult(cacheValue)
                {
                    StatusCode = 200,
                };
            }
        }
        void IResourceFilter.OnResourceExecuted(ResourceExecutedContext context)
        {
            // 如果缓存中不存在数据,将数据添加到缓存中
            if (!Cache.ContainsKey(CacheKey))
            {
                Cache.Add(CacheKey, context.Result);
            }
        }       
    }
}

4、异常处理过滤器

异常处理过滤器(Exception Filters)在 ASP.NET Core 中用于捕获控制器动作或整个控制器中抛出的异常。这些过滤器可以用于日志记录、异常转换、返回自定义错误响应等。通过使用异常处理过滤器,开发者可以统一处理错误,而无需在每个控制器或动作方法中重复相同的错误处理逻辑。

使用场景

异常处理过滤器通常用于:

  • 错误日志记录:记录错误详细信息,例如堆栈跟踪、请求信息等。
  • 统一错误响应格式:确保所有API错误都返回一致的响应格式。
  • 异常转换:将特定类型的异常转换为更具体的HTTP状态码或错误消息。
  • 异常处理策略:根据不同的异常类型或内容应用不同的处理策略。
using Microsoft.AspNetCore.Mvc.Filters;

namespace AopDemo.Filter
{
    public class LoggingActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // 在Action方法执行之前执行
            //从请求中获取服务的provider
            var logger = context.HttpContext.RequestServices.GetService(typeof(ILogger<LoggingActionFilter>)) as ILogger<LoggingActionFilter>;
            var path = context.HttpContext.Request.Path;
            var controllerName = context.RouteData.Values["controller"];
            var actionName = context.RouteData.Values["action"];
            var actionArguments = string.Join(",", context.ActionArguments.Select(a => a.Key + ":" + a.Value));
            logger.LogInformation($"Action开始执行:{controllerName}.{actionName},参数:{actionArguments}");
            // 这里可以写一些逻辑代码
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            // 在Action方法执行后执行
            // 这里可以写一些逻辑代码
        }
    }
}

5、操作过滤器

ActionFilter 是一种常见的过滤器,用于拦截和操作控制器的动作方法请求和响应。它是 ASP.NET Core 中过滤器管道的一部分,可以用于跨多个控制器或动作执行逻辑。

日志记录
using Microsoft.AspNetCore.Mvc.Filters;

namespace AopDemo.Filter
{
    public class LoggingActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // 在Action方法执行之前执行
            //从请求中获取服务的provider
            var logger = context.HttpContext.RequestServices.GetService(typeof(ILogger<LoggingActionFilter>)) as ILogger<LoggingActionFilter>;
            var path = context.HttpContext.Request.Path;
            var controllerName = context.RouteData.Values["controller"];
            var actionName = context.RouteData.Values["action"];
            var actionArguments = string.Join(",", context.ActionArguments.Select(a => a.Key + ":" + a.Value));
            logger.LogInformation($"Action开始执行:{controllerName}.{actionName},参数:{actionArguments}");
            // 这里可以写一些逻辑代码
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            // 在Action方法执行后执行
            // 这里可以写一些逻辑代码
        }
    }
}
验证

ActionFilter 中检查模型是否有效,避免在每个动作方法中重复验证逻辑

public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值