CORS概念
例如,http://foo.com 中某个网页上的 JavaScript 无法对 http://bar.com(或 http://www.foo.com、https://foo.com 或 http://foo.com:999 等)进行 AJAX 调用。
通过 Web API 2,您可以对策略进行配置以允许不同域的 JavaScript 客户端访问您的 API。
CORS 基本信息
这些详细内容现在看起来可能都是理论之谈,但对于以后了解 Web API 中的可用设置来说将十分有用:在您调试 CORS 时,这些内容有助于您更快速地解决问题。
这种权限检查将针对客户端调用的每个不同 URL 进行,这就意味着不同的 URL 可以具有不同权限。
图 1 总结了这些标头(请注意,一些功能没有在响应中发送的标头,仅有响应)。
图 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 请求。
Web API 2 对 CORS 的支持
该框架围绕一个策略方案展开,该策略方案可让您指定针对进入应用程序的任何给定请求而允许的 CORS 功能。
Install-Package Microsoft.AspNet.WebApi.Cors
注意 Web api 2对,net framework的要求必须是4.5以上,安装完上面的package后,会发现引用中多了两个重要的包,如下图所示
此类包含允许的域、HTTP 方法、请求标头、响应标头以及是否允许使用凭据等方面的属性(它们对前面所述的 CORS 规范的所有详细信息进行建模)。
对于 CORS 请求,该处理程序会查询在所调用方法的属性中表达的策略,并发出适当的 CORS 响应标头。
这些参数(依次)为:
- 允许域列表
- 允许请求标头列表
- 允许 HTTP 方法列表
- 允许响应标头列表(可选)
还有一个允许使用凭据的属性 (SupportsCredentials) 以及另一个用于指定预检缓存持续时间值的属性 (PreflightMaxAge)。
以vs2013建立的默认api程序为例,建完webapi引用程序后在Controller文件夹下会自动生成两个控制区,一个HomeController和一个ValueController,我们主要看一下ValueControll,这个控制器继承了ApiController,可见是一个webapi,我们在valueController上添加一个全局的 EnableCors属性,以试它支持跨域,如下图所示
如果您想允许所有域、请求标头或 HTTP 方法,则可以使用“*”作为值(对于响应标头仍须显式指定)。
最后,如果全局应用该策略,则该策略将应用于所有请求。
此属性实质上是一个没有允许权限的策略。
或者,您可以保留通配符,但使用 DisableCors 属性来排除 Delete 方法。
消息处理程序的启用通常是在应用程序的 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" />
<div ></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,返回结果如下图所示
可以看出,其实浏览器发出了两次请求。
自定义策略
虽然这样做在开发过程中或在特定情况下可能行得通,但如果需要动态确定域列表或其他权限(比如,从数据库获取),则静态列表就不够用了。
明天在给大家介绍 WebApi自定义跨域策略,就是把域存在数据库或者配置文件中,程序可以动态的修改允许的域的请求~~