ASP.NET Web API 2 对 CORS 的支持

CORS概念javascript

跨域资源共享 (CORS) 是一种万维网联合会 (W3C) 规范(一般被认为是 HTML5 的一部分),它可以让 JavaScript 克服由浏览器施加的同域策略安全限制。 所谓同域策略,就是 JavaScript 只能对包含网页的同一个域进行 AJAX 回调(其中,“域”就是主机名、协议和端口号的组合)。 例如,http://foo.com 中某个网页上的 JavaScript 没法对 http://bar.com(或 http://www.foo.com、https://foo.com 或 http://foo.com:999 等)进行 AJAX 调用。html

CORS 可以让服务器指明容许哪些域对它们进行调用,从而放宽这种限制。 CORS 是由浏览器强制执行的,而且必须在服务器上实现,而最新版本的 ASP.NET Web API 2 全面支持 CORS。 经过 Web API 2,您能够对策略进行配置以容许不一样域的 JavaScript 客户端访问您的 API。java

CORS 基本信息

因为 Web API 彻底按照该规范来实现,所以,为了使用 Web API 中的新 CORS 功能,详细了解 CORS 自己将大有帮助。 这些详细内容如今看起来可能都是理论之谈,但对于之后了解 Web API 中的可用设置来讲将十分有用:在您调试 CORS 时,这些内容有助于您更快速地解决问题。jquery

CORS 的通常机制是,当 JavaScript 尝试进行跨域 AJAX 调用时,浏览器会经过在 HTTP 请求中发送标头(如“Origin”)来“询问”服务器是否容许进行这样的调用。 服务器经过在响应中返回 HTTP 标头(如“Access-Control-Allow-Origin”)指明容许的操做。 这种权限检查将针对客户端调用的每一个不一样 URL 进行,这就意味着不一样的 URL 能够具备不一样权限。web

除域以外,CORS 还可让服务器指明容许使用的 HTTP 方法、客户端能够发送的 HTTP 请求标头、客户端能够读取的 HTTP 响应标头以及是否容许浏览器自动发送或接收凭据(Cookie 或受权标头)。 其余请求和响应标头指明容许使用其中的哪些功能。 图 1 总结了这些标头(请注意,一些功能没有在响应中发送的标头,仅有响应)。ajax

图 1 CORS HTTP 标头数据库

权限/功能 请求标头 响应标头
Access-Control-Allow-Origin
HTTP 方法 Access-Control-Request-Method Access-Control-Allow-Method
请求标头 Access-Control-Request-Headers Access-Control-Allow-Headers
响应标头   Access-Control-Expose-Headers
凭据   Access-Control-Allow-Credentials
缓存预检响应   Access-Control-Max-Age

浏览器可经过两种不一样的方式向服务器请求这些权限:简单 CORS 请求和预检 CORS 请求。api

 

Web API 2 对 CORS 的支持

Web API 中对 CORS 的支持是一个完整框架,容许应用程序定义 CORS 请求的权限。 该框架围绕一个策略方案展开,该策略方案可以让您指定针对进入应用程序的任何给定请求而容许的 CORS 功能。跨域

首先,为了获取该 CORS 框架,您必须从 Web API 应用程序引用 CORS 库(默认状况下,Visual Studio 2013 中的任何 Web API 模板都不引用这些库)。 该 Web API CORS 框架经过 NuGet 做为 Microsoft.AspNet.WebApi.Cors 程序包提供。 早 nuget中输入
浏览器

Install-Package Microsoft.AspNet.WebApi.Cors

注意 Web api 2对,net framework的要求必须是4.5以上,安装完上面的package后,会发现引用中多了两个重要的包,以下图所示

 

接下来,为了表达该策略,Web API 提供了一个名为 EnableCorsAttribute 的自定义属性类。 此类包含容许的域、HTTP 方法、请求标头、响应标头以及是否容许使用凭据等方面的属性(它们对前面所述的 CORS 规范的全部详细信息进行建模)。

最后,为了让 Web API CORS 框架处理 CORS 请求并发出适当的 CORS 响应标头,该类必须检查进入应用程序的每一个请求。 Web API 经过消息处理程序提供用于这种拦截操做的扩展点。 Web API CORS 框架会相应地实现一个名为 CorsMessageHandler 的消息处理程序。 对于 CORS 请求,该处理程序会查询在所调用方法的属性中表达的策略,并发出适当的 CORS 响应标头。

EnableCorsAttribute。EnableCorsAttribute 类就是应用程序表达其 CORS 策略的方式。EnableCorsAttribute 类有一个可接受三个或四个参数的重载构造函数。 这些参数(依次)为:

  1. 容许域列表
  2. 容许请求标头列表
  3. 容许 HTTP 方法列表
  4. 容许响应标头列表(可选)

还有一个容许使用凭据的属性 (Supports­Credentials) 以及另外一个用于指定预检缓存持续时间值的属性 (PreflightMaxAge)。

 

以vs2013创建的默认api程序为例,建完webapi引用程序后在Controller文件夹下会自动生成两个控制区,一个HomeController和一个ValueController,咱们主要看一下ValueControll,这个控制器继承了ApiController,可见是一个webapi,咱们在valueController上添加一个全局的 EnableCors属性,以试它支持跨域,以下图所示

请注意,每一个构造函数参数都是一个字符串。 经过指定逗号分隔列表,能够表示多个值。 若是您想容许全部域、请求标头或 HTTP 方法,则可使用“*”做为值(对于响应标头仍须显式指定)。

除在方法级别应用 EnableCors 属性外,还能够在类级别应用该属性,或将其全局应用于应用程序。 应用该属性的级别会在 Web API 代码中为该级别及下面级别的全部请求配置 CORS。 例如,若是在方法级别应用该策略,则该策略仅应用于该操做的请求,而若是在类级别应用该策略,则该策略将应用于对该控制器的全部请求。 最后,若是全局应用该策略,则该策略将应用于全部请求。

若是在多个位置存在策略,则会使用“最接近的”属性,并忽略其余属性(优先顺序是方法、类、全局)。 若是您已在较高级别上应用策略,但随后想在较低级别上排除某一请求,则可使用名为 DisableCorsAttribute 的另外一个属性类。 此属性实质上是一个没有容许权限的策略。

若是在您不想容许 CORS 的控制器上有其余方法,则有两个选择。 首先,您可在 HTTP 方法列表中显式指定。 或者,您能够保留通配符,但使用 DisableCors 属性来排除 Delete 方法。

CorsMessageHandler。必须为 CORS 框架启用 CorsMessageHandler,才能执行其为评估 CORS 策略并发出 CORS 响应标头而拦截请求的工做。 消息处理程序的启用一般是在应用程序的 Web API 配置类中经过调用 EnableCors 扩展方法进行的:

  public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务

            // Web API 路由
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

       //启用跨域  
            config.EnableCors();
        }
    }

 

 

在浏览器中输入http://localhost:19881/api/values出现以下,说明该weapi已经可用。

那么接下来,咱们就要测试跨域了,新建一个mvc应用程序,制定端口号为19894

其中home/index页面的代码以下所示

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
</head>
<body>
    <div>
        <input type="button" id="cros" value="获取跨域" />
        <div id="msg"></div>
    </div>
    <script type="text/javascript">
        $(function () {
            $("#cros").click(function () {
                $.ajax({
                    url: "http://localhost:19881/api/values",
                    type: "get",
                    success: function (d) {
                        $("#msg").html(d)
                    }
                });
            });
        });
    </script>
</body>

</html>

  

代码很简单,就防放置一个按钮,用ajax的方式请求不一样域下的webapi,返回结果以下图所示

能够看出,其实浏览器发出了两次请求。

 

自定义策略

从前面的示例可明显看到,域列表(若是未使用通配符)是一个编译到 Web API 代码中的静态列表。 虽然这样作在开发过程当中或在特定状况下可能行得通,但若是须要动态肯定域列表或其余权限(好比,从数据库获取),则静态列表就不够用了。

明天在给你们介绍 WebApi自定义跨域策略,就是把域存在数据库或者配置文件中,程序能够动态的修改容许的域的请求~~

相关文章
相关标签/搜索