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
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2018-11-07 21:24  花道长  阅读(272)  评论(0编辑  收藏  举报