ASP.NET Web API自身对CORS的支持: CORS授权检验的实施

通过《EnableCorsAttribute特性背后的故事》我们知道:由CorsPolicyProvider提供的CorsPolicy表示目标Action采用的资源授权策略,ASP.NET Web API最终需要利用它对具体的跨域资源请求实施授权检验并生成相应的CORS响应报头。在ASP.NET Web API的应用编程接口中,资源授权检验的结果通过类型CorsResult来表示。

一、CorsResult

CorsResult定义在命名空间“System.Web.Cors”下,表示资源提供者针对具体跨域资源请求进行授权检验得到的结果,最终写入响应的CORS报头均通过此对象来生成。如下面的代码片断所示,CorsResult依然具有与6个CORS响应报头对应的属性,通过其方法ToResponseHeaders方法的字典表示由此6个属性生成的CORS相应报头,字典对象的Key和Value分别表示报头名称和值。

   1: public class CorsResult
   2: {
   3:     public string            AllowedOrigin { get; set; }
   4:     public IList<string>     AllowedExposedHeaders { get; }
   5:     public IList<string>     AllowedHeaders { get; }
   6:     public IList<string>     AllowedMethods { get; }
   7:     public long?             PreflightMaxAge { get; set; }
   8:     public bool              SupportsCredentials { get; set; }
   9:     
  10:     public IList<string>     ErrorMessages { get; }
  11:     public bool              IsValid { get; }
  12:  
  13:     public virtual IDictionary<string, string> ToResponseHeaders();
  14: }

CorsResult具有一个布尔类型的属性IsValid表示请求是否通过资源授权检验。如果该属性返回False(没有通过资源授权检验),另一个相关的属性ErrorMessages会提供导致检验失败的原因。IsValid是一个只读属性,它的值取决于通过ErrorMessages属性表示的字符串列表是否为空。

二、CorsRequestContext

针对CORS的支持其实并不限于仅被使用在ASP.NET Web API上,用于根据提供的资源授权策略对跨域资源请求进行授权检验得引擎定义在程序集System.Web.Cors.dll中,定义在另一个程序集对于这些类型来说,除了CorsPolicy定义在程序集System.Web.Cors.dll,其余的类型均定义在程序集System.Web.Http.Cors.dll中的相关类型可以视为对这个核心CORS引擎的扩展。对于本节引入的类型来说,它具有的命名空间其实也体现了它所在的程序集。

对于ASP.NET Web API来说,CORS资源授权检验实施的目标是表示当请求的HttpRequestMessage对象,这个对象自然不可能使用在ASP.NET的核心CORS引擎中。对于后者,授权检验是针对一个System.Web.Cors.CorsRequestContext对象,它代表针对当前请求的上下文。如下面的代码片断所示,我们可以通过CorsRequestContext对象得到对应HTTP请求的地址(RequestUri)、主机名称(Host)和采用的HTTP方法(HttpMethod)。

   1: public class CorsRequestContext
   2: {
   3:     public Uri         RequestUri { get; set; }
   4:     public string      Host { get; set; }
   5:     public string      HttpMethod { get; set; }    
   6:    
   7:     public string          Origin { get; set; }
   8:     public bool            IsPreflight { get; }
   9:     public string          AccessControlRequestMethod { get; set; }
  10:     public ISet<string>    AccessControlRequestHeaders { get; }
  11:  
  12:     public IDictionary<string, object> Properties { get; }
  13: }

CorsRequestContext的Origin属性返回通过请求的“Origin”报头表示的源站点。我们可以利用其IsPreflight属性判断HTTP请求是否为一个预检请求,这里对预检请求的判断标准与我们前面演示实例采用的完全一致:采用HTTP-OPTIONS方法摒弃同时具有“Origin”和“Access-Control-Request-Method”报头。

对于针对预检请求的CorsRequestContext,我们可以通过其属性AccessControlRequestMethod和AccessControlRequestHeaders得到请求报头“Access-Control-Request-Method”和“Access-Control-Request-Headers”的值。通过另一个字典类型的只读属性Properties,我们可以将任意对象作为属性附加到该CorsRequestContext对象上。

三、CorsEngine

我们说ASP.NET 的核心CORS引擎定义在程序集System.Web.Cors.dll中,它主要体验为这个名为CorsEngine的对象,其主要的使命在于:根据提供的资源授权策略(通过CorsPolicy类型表示)针对具体的跨域资源请求(通过CorsRequestContext类型表示)实施授权检验并得到相应的授权结果(通过CorsResult表示)。所有的CorsEngine类型均实现System.Web.Cors.ICorsEngine接口,如下面的代码片断所示,跨域资源请求的授权检查就实现在其唯一的EvaluatePolicy方法中。

   1: public interface ICorsEngine
   2: {
   3:     CorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy);
   4: }

在程序集System.Web.Cors.dll中定义了唯一的实现了ICorsEngine接口,即具有如下定义的类型System.Web.Cors.CorsEngine。如下面的代码片断所示,CorsEngine类型定义了3个辅助的虚方法(TryValidateOrigin、TryValidateMethod 和TryValidateHeaders)分别针对请求的源站点以及请求采用的HTTP方法和自定义报头实施授权检验,其中后面两个方法是专门为预检请求设计的。

   1: public class CorsEngine : ICorsEngine
   2: {
   3:     public virtual CorsResult EvaluatePolicy(CorsRequestContext requestContext, CorsPolicy policy);
   4:  
   5:     public virtual bool TryValidateOrigin(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
   6:     public virtual bool TryValidateMethod(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result);
   7:     public virtual bool TryValidateHeaders(CorsRequestContext requestContext, CorsPolicy policy, CorsResult result); 
   8: }

CorsPolicyProviderFactory一样,ASP.NET Web API使用的CorsEngine需要注册到当前HttpConfiguration,注册的CorsEngine同样是被添加到HttpConfiguration的属性字典之中。CorsEngine的注册可以通过调用HttpConfiguration如下所示的扩展方法SetCorsEngine来完成。另一个扩展方法GetCorsEngine用于获取注册的CorsEngine,如果在调用此方法时CorsEngine尚未被注册,一个CorsEngine对象会被创建出来并自动注册到HttpConfiguration上。

   1: public static class CorsHttpConfigurationExtensions
   2: {
   3:     //其他成员
   4:     public static void SetCorsEngine(this HttpConfiguration httpConfiguration, ICorsEngine corsEngine);
   5:     public static ICorsEngine GetCorsEngine(this HttpConfiguration httpConfiguration);
   6: }

CORS系列文章 [1] 同源策略与JSONP [2] 利用扩展让ASP.NET Web API支持JSONP [3] W3C的CORS规范 [4] 利用扩展让ASP.NET Web API支持CORS [5] ASP.NET Web API自身对CORS的支持: 从实例开始 [6] ASP.NET Web API自身对CORS的支持: CORS授权策略的定义和提供 [7] ASP.NET Web API自身对CORS的支持: CORS授权检验的实施 [8] ASP.NET Web API自身对CORS的支持: CorsMessageHandler

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

Asp.Net MVC4入门指南(2):添加一个控制器

MVC代表: 模型-视图-控制器 。MVC是一个架构良好并且易于测试和易于维护的开发模式。基于MVC模式的应用程序包含: · Models: 表示该应用程序的数...

1967
来自专栏用户2442861的专栏

JSP常用跳转方式

http://blog.csdn.net/wanghuan203/article/details/8836326#comments

2791
来自专栏CDA数据分析师

学会这几招,轻松掌握Python文件管理

一、Python中的文件管理 文件管理是很多应用程序的基本功能和重要组成部分。Python可以使文件管理极其简单,特别是和其它语言相对比。 以下,Peyton ...

2986
来自专栏Golang语言社区

Go语言学习(一):hello world

每学一门语言,程序猿们总是不厌其烦地写一遍hello world,这篇就是Go语言的hello world。 Go语言的环境搭建建议参考《Go We...

3216
来自专栏linux驱动个人学习

VFS四大对象之二 struct inode

继上一篇文章:https://cloud.tencent.com/developer/article/1053842 二、inode结构体:(转自http://...

5667
来自专栏张善友的专栏

.NET 异常处理的动作策略(Action Policy)

SQL Server 2008基于策略的管理,基于策略的管理(Policy Based Management),使DBA们可以制定管理策略,并将这些策略应用到服...

2007
来自专栏风中追风

java类的加载过程和类加载器的分析

我们知道,我们写的java代码保存的格式是 .java, java文件被编译后会转换为字节码,字节码可以在任何平台通过java虚拟机来运行,这也是java能够跨...

5478
来自专栏炉边夜话

JNI使用技巧点滴(二)

作者:normalnotebook 背景<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com...

1742
来自专栏青玉伏案

iOS开发之再探多线程编程:Grand Central Dispatch详解

Swift3.0相关代码已在github上更新。之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread、操作队列以及GCD,介绍的不够深入。今...

1967
来自专栏张善友的专栏

Enterprise Library 4 数据访问应用程序块

Enterprise Library 数据访问应用程序块简化了实现常规数据访问功能的开发任务。应用程序可以在各种场景中使用此应用程序块,例如为显示而读取数据、传...

3186

扫码关注云+社区

领取腾讯云代金券