Web APi之过滤器执行过程原理解析【二】(十一)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要。这一节我们简单将讲述在Action方法上、控制器上、全局上以及授权上的自定义特性的执行过程。

前言

上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要。这一节我们简单将讲述在Action方法上、控制器上、全局上以及授权上的自定义特性的执行过程。

APiController 

之前有讲到该APiController,也就稍微介绍了,这节我们来详细此Web API控制器的基类:

 1 public abstract class ApiController : IHttpController, IDisposable
 2 {
 3     // Fields
 4     private HttpConfiguration _configuration;
 5     private HttpControllerContext _controllerContext;
 6     private bool _disposed;
 7     private ModelStateDictionary _modelState;
 8     private HttpRequestMessage _request;
 9     private UrlHelper _urlHelper;
10 
11     // Methods
12     protected ApiController();
13     public void Dispose();
14     protected virtual void Dispose(bool disposing);
15     public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken);
16     protected virtual void Initialize(HttpControllerContext controllerContext);
17     internal static Func<Task<HttpResponseMessage>> InvokeActionWithActionFilters(HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IActionFilter> filters, Func<Task<HttpResponseMessage>> innerAction);
18     internal static Func<Task<HttpResponseMessage>> InvokeActionWithAuthorizationFilters(HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IAuthorizationFilter> filters, Func<Task<HttpResponseMessage>> innerAction);
19     internal static Task<HttpResponseMessage> InvokeActionWithExceptionFilters(Task<HttpResponseMessage> actionTask, HttpActionContext actionContext, CancellationToken cancellationToken, IEnumerable<IExceptionFilter> filters);
20 
21     // Properties
22     public HttpConfiguration Configuration { get; set; }
23     public HttpControllerContext ControllerContext { get; set; }
24     public ModelStateDictionary ModelState { get; }
25     public HttpRequestMessage Request { get; set; }
26     public UrlHelper Url { get; set; }
27     public IPrincipal User { get; }
28 
29     // Nested Types
30     private class FilterGrouping
31     {
32         // Fields
33         private List<IActionFilter> _actionFilters;
34         private List<IAuthorizationFilter> _authorizationFilters;
35         private List<IExceptionFilter> _exceptionFilters;
36 
37         // Methods
38         public FilterGrouping(IEnumerable<FilterInfo> filters);
39         private static void Categorize<T>(IFilter filter, List<T> list) where T: class;
40 
41         // Properties
42         public IEnumerable<IActionFilter> ActionFilters { get; }
43         public IEnumerable<IAuthorizationFilter> AuthorizationFilters { get; }
44         public IEnumerable<IExceptionFilter> ExceptionFilters { get; }
45     }
46 }

我们首先来看看此类中的一个私有类 FilterGrouping ,顾名思义是对过滤器分组,我们查看其构造函数看看:

public FilterGrouping(IEnumerable<FilterInfo> filters)
{
    this._actionFilters = new List<IActionFilter>();
    this._authorizationFilters = new List<IAuthorizationFilter>();
    this._exceptionFilters = new List<IExceptionFilter>();
    foreach (FilterInfo info in filters)
    {
        IFilter instance = info.Instance;
        Categorize<IActionFilter>(instance, this._actionFilters);
        Categorize<IAuthorizationFilter>(instance, this._authorizationFilters);
        Categorize<IExceptionFilter>(instance, this._exceptionFilters);
    }
}

我们仅仅只需 _actionFilters 为例,其余一样,我们再来看看 Categorize 方法:

1 private static void Categorize<T>(IFilter filter, List<T> list) where T: class
2 {
3     T item = filter as T;
4     if (item != null)
5     {
6         list.Add(item);
7     }
8 }

从这里我们可以得知:

当我们在HttpActionDescriptor初始化创建了封装了Filter对象的FilterInfo的集合列表,此时然后利用此类中的三个属性类型:IActionFilter、IAuthorizationFilter、以及IExceptionFilter进行过滤器分组得到对应过滤器集合列表

执行过程原理解析 

下面我们通过例子来看看之执行过程,我们自定义以下五个过滤器

 /// <summary>
    /// 全局的行为过滤器
    /// </summary>
    public class CustomConfigurationActionFilterAttribute : FilterAttribute, IActionFilter
    {
        public Task<HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            Console.WriteLine(this.GetType().Name);
            return continuation();
        }
    }

    /// <summary>
    /// 控制器级行为过滤器
    /// </summary>
    public class CustomControllerActionFilterAttribute : FilterAttribute, IActionFilter
    {
        public Task<HttpResponseMessage> ExecuteActionFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            Console.WriteLine(this.GetType().Name);
            return continuation();
        }
    }

    /// <summary>
    /// 控制器方法级行为过滤器
    /// </summary>
    public class CustomActionFilterAttribute : FilterAttribute, IActionFilter
    {
        public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            Console.WriteLine(this.GetType().Name);
            return continuation();
        }
    }

    /// <summary>
    /// 控制器级授权访问过滤器
    /// </summary>
    public class CustomControllerAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter
    {
        public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            Console.WriteLine(this.GetType().Name);
            return continuation();
        }
    }

    /// <summary>
    /// 控制器方法级授权访问过滤器
    /// </summary>
    public class CustomControllerActionAuthorizationFilterAttribute : FilterAttribute, IAuthorizationFilter
    {
        public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
        {
            Console.WriteLine(this.GetType().Name);
            return continuation();
        }
    }

接下来就是实现过滤器,配置文件中配置全局过滤器

  config.Filters.Add(new CustomConfigurationActionFilterAttribute());

控制器及方法上过滤器

    [CustomControllerAuthorizationFilter]
    [CustomControllerActionFilter]
    public class ProductController : ApiController
    {
        [CustomActionFilter]
        [CustomControllerActionAuthorizationFilter]
        public string GetFilter()
        {
            var sb = new StringBuilder();

            var actionSelector = this.Configuration.Services.GetActionSelector();
            var actionDesciptor = actionSelector.SelectAction(this.ControllerContext);
            foreach (var filterInfo in actionDesciptor.GetFilterPipeline())
            {
                sb.AppendLine("【FilterName:" + filterInfo.Instance.GetType().Name + ",FilterScope:" + filterInfo.Scope.ToString() + "】");
            }
            return sb.ToString();
        }
    }

最后来查看其结果:

看到这里是不是有点疑惑怎么按照Global->Controller->Action来进行排序,如果你看过前面文章就会知道这是过滤器管道按照FilterScope来生成的,实际上在服务器端生成的顺序为 CustomControllerAuthorizationFilterAttribute 、 CustomControllerActionAuthorizationFilterAttribute 、 CustomConfigurationActionFilterAttribute 、 CustomControllerActionFilterAttribute 以及 CustomActionFilterAttribute 由此我们得出结论:

授权过滤器不管任何的FilterScope都是优于行为过滤器,而在同一种类型的过滤器中是根据FilterScope来确定执行顺序的。 

总结 

有关更多深入的内容就不再探讨,本想多写一点,但是状态不佳加上更多内容比较复杂以免说不太明白云里雾里,想想还是算了,就这样了,下面还是给出其一张执行的详细示意图,来源【过滤器执行过程

  

接下来将通过实例详细讲解Web API中的认证(Authentication)以及授权(Authorization),敬请期待。。。。。。

 

目录
相关文章
|
数据采集 算法 Java
全国快递物流 API 实现快递单号自动识别的原理解析
全国快递物流 API 实现快递单号自动识别的原理解析
653 0
|
存储 算法 安全
【精通函数式编程】(四)流-Stream API原理解析
本文通过集合引出Stream流,主要讲解了流的基本概念、使用的原理,Stream流水线的运行原理
【精通函数式编程】(四)流-Stream API原理解析
|
SQL 存储 分布式计算
【spark系列5】spark 3.0.1集成delta 0.7.0原理解析--delta如何进行DDL DML操作以及Catalog plugin API
【spark系列5】spark 3.0.1集成delta 0.7.0原理解析--delta如何进行DDL DML操作以及Catalog plugin API
409 0
|
消息中间件 Kafka API
Kafka原理解析-旧版本0.8高级Api的Demo和配置信息获取技巧
旧版本高级Api封装: package xxxxxx; import kafka.producer.KeyedMessage; import kafka.producer.ProducerConfig; import java.util.Properties; public class KafkaProducerTest implements Runnable {
558 0
|
API 容器 .NET
Web APi之过滤器创建过程原理解析【一】(十)
前言 Web API的简单流程就是从请求到执行到Action并最终作出响应,但是在这个过程有一把【筛子】,那就是过滤器Filter,在从请求到Action这整个流程中使用Filter来进行相应的处理从而作出响应,这对于认证以及授权等是及其重要的,所以说过滤器应用是Web API框架中非常重要的一种实现方式,我们有必要去探讨其原理。
1035 0
|
17天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
75 3