asp.net web api 2 对跨域资源共享的支持
1. 同源策略:
同源策略是浏览器为保证安全最基本的功能, 只有同源的脚本才能够被执行,那么什么是同源呢?同源是指协议,域名以及端口号都相同,任何一个不同的都不为同源资源,即异源。
2. 跨域访问Api接口:
在面向服务架构的项目开发过程中,我们往往会面对对于跨域资源的访问,由于浏览器的同源策略,它会阻止我们去访问异源资源,那么在我们编写好我们的api接口之后, 我们需要如何在跨域的情况下访问我们的
api接口呢? 在asp.net web api 2.0中, 我们可以使用 CorsMessageHandler 类来处理 Cors (Cross-origin resource sharing)请求, 首先我们可以通过 工具-> Nuget程序包管理器 -> 程序包管理器控制台, 键入:
install-package Microsoft.AspNet.WebApi.Cors
来获取 Microsoft.AspNet.Cors.5.0.0 和 Microsoft.AspNet.WebApi.Cors.5.0.0 这两个包,我们的项目便会引入 System.Web.Cors.dll 和 System.Web.Http.Cors.dll 两个程序集, 下面, 我们
需要对程序进行配置以达到对 Cors的支持, 首先我们可以在 Global.asax 文件中的 Application_Start 方法中对 Cors 进行启用:
GlobalConfiguration.Configuration.EnableCors();
注意:这一句一定要放在
GlobalConfiguration.Configure(WebApiConfig.Register);
1
这一句之前,博主之前由于讲这句代码放置在后者之后, 也就是当 GlobalConfiguration完成对 WebApiConfig配置之后再进行启用 Cors ,所以完全就没有起到丝毫作用, 血的教训, 至于我是怎么发现这个错误的,是因为可以启用 Cors 的位置还有一个, 那就是在 WebApiConfig.cs 文件中:
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
当我们这样设置完成之后, 我们的程序就可以启用 Cors 请求来对我们的 Api 资源进行访问, 下面一步需要我们对 Controller进一步控制, 我们可以将 EnableCorsAttribute 特效放置在Controller之上, 这样就起到了对整个 Controller 所有 Action 的 Cors 控制 :
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class GoodController : ApiController
{
}
EnableCorsAttribute 的构造函数有两个, 签名分别为:
EnableCorsAttribute(string origin, string headers, string methods)
EnableCorsAttribute(string origin, string headers, string methods, string exposedHeaders)
origin : 允许被访问的资源列表,使用逗号分隔, * 表示全部支持
headers : 资源所支持的标头列表,使用逗号分隔, * 表示全部支持, null表示都不支持
methods : 资源所支持的方法列表,使用逗号分隔, * 表示全部支持, null表示都不支持
exposedHeaders : 资源所支持且可公开的标头列表,使用逗号分隔, 默认都不公开
当然,EnableCorsAttribute 也可以附加在 Action 上, 这样就只会在附加了此特性的 Action 起到控制作用, 当然, 当我在 Controller 上附加了 EnableCorsAttribute 特性之后,又不想在此 Controller 的部分 Action 上启用 Cors 访问, 那么可以在这些 Action 上附加 DisableCorsAttribute 特性,这样就可以解决这个问题。
我在控制器上附加了
[EnableCors(origins: "*", headers: "*", methods: "*")]
1
如果大家只想将 api 给自己某几个引用使用的话, 那么可以在 origins 中添加自己想要给予访问权限的应用地址, 如:
[EnableCors(origins: "http://www.exampleA.com, http://www.exampleB.com", headers: "*", methods: "*")]
1
这样设置之后, 只有就只有 http://www.exampleA.com, http://www.exampleB.com 这两个站点的应用可以跨域来访问我们的api 资源。
下面,我们来对比一下未启用 Cors 和启用 Cors 的情景:
未启用 Cors, 我们会发现在浏览器的开发者工具的控制台中:
未启用 Cors
当我们试图去请求一个不支持跨域资源共享的api时, 浏览器会返回给我们一个 405 (Method Not Allowed) , 下面一样提示我们没有权限去访问此 api接口 。
启用 Cors :
启用 Cors 之后
3. 其他的几种跨域请求方式:
当然, 为了我们的应用可以访问跨域资源的方法有很多, 博主所介绍的只是其中的一种而已, 具有所知还有大概一下几种:
使用 script 标签:
<script type="text/javascript" src="http://localhost:5267/api/good?callback=jsonpCallback"></script>
<script type="text/javascript">
function jsonpCallback(data){
}
</script>
1
2
3
4
5
6
由于带有src属性的标签都是具有跨域资源请求能力的,所以我们可以借助这一点待完成跨域,但是注意, 使用着一种方式需要在你申明 api所返回的数据中做一些细微处理:
request["callback"]+"("+返回的原始数据+")"
1
例如你要返回的 json数据为
{id:'s001', name: '...'}
1
而你请求中的callback参数为 jsonpCallback,通过 request获取 callback 参数之后, 需要这样处理:
jsonpCallback({id:'s001', name: '...'})
1
使用 $.ajax:
$.ajax({
type: 'get',
url: '你的api地址',
dataType: 'jsonp'
}).done(
function(data){
}
);
其实使用上面的这种方式,实际上产生的效果是与第一种是一样的,当我们发送请求之后, 我们观察请求类型, 实际上也是请求了一个 script。 注意一点,如果使用构造 script 的方式来请求跨域,
那么我们是无法使用除 get方式之外的请求方式的, 这个也是这种方式相当大的一个缺陷。
使用 $.ajax 的 crossDomain :
具体 api 文档可以参考 http://api.jquery.com/jQuery.ajax/
这种方式是构建 XMLHttpRequest 请求, 具体可参考: http://www.html5rocks.com/en/tutorials/cors/#toc-types-of-cors-requests
后面我将案例完善之后, 我会将源码一并贴出来, 是一个基于 asp.net web api 2.0 + knockout.js 的案例。
---------------------
作者:Rajesh_James
来源:CSDN
原文:https://blog.csdn.net/zhanxueguang/article/details/46821511
版权声明:本文为博主原创文章,转载请附上博文链接!