在执行下面那段代码的时候,我遇到了一个跨域资源共享的问题

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script type="text/javascript" src="jquery-1.11.3.js"></script>
</head>
<script>
    $(function(){
        $('#ok').click(function(){
            var aa=$('#wd').val();
            $.get("http://www.baidu.com/s",{wd:aa},function(data){
                    $('#show').html(data);
            });    
        });    
    });
</script>

<body>
key:<input type="text" name="wd" id="wd"/>
<input type="button" value="ok" id="ok"/>
<div id="show" style="width:600px; height:600px; border:1px #00FF00"></div>
</body>
</html>

cors跨域资源共享】同源策略和jsonp

Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分。“同源策略”限制了JavaScript的跨站点调用,这必然导致Web API不能垮域提供资源。如果Web API仅限于为“同源客户端”提供资源,那么它都对不起自己的名字,因为Web本身是一个开放的协议。那么ASP.NET Web API通过怎样的方式来实现跨域资源共享呢?
同源策略

浏览器是访问Internet的工具,也是客户端应用的宿主,它为客户端应用提供一个寄宿和运行的环境。而这里所说的应用,基本是指在浏览器中执行的客户端JavaScript程序。虽然是一种解释性的脚本语言,JavaScript其实是无比强大的,原则上来讲它可以做任何事。但是在能够在JavaScript脚本并不都是值得信赖的,所以浏览器必须对JavaScript的执行作相应的限制,这就是我们接下来着重介绍的“同源策略(Same Origin Policy)”。

同源策略是浏览器的一项最为基本同时也是必须遵守的安全策略,毫不夸张地说,浏览器的整个安全体系均建立在此之上。同源策略的存在,限制了“源”自A的脚本只能操作“同源”页面的DOM,“跨源”操作来源于B的页面将会被拒绝。所谓的“同源”,必须要求相应的URI在如下3个方面均是相同的。术语“源(Origin)”在中文表达中显得有点突兀,所以在接下来的内容中,我们更多地会采用“站点(Site)”或者“域(Domain)”这样的说法,在未作特别说明的情况下均与“源”表达相同的意思。

主机名称(域名/子域名或者IP地址)
    端口号
    网络协议(Scheme,分别采用“http”和“https”协议的两个URI被视为不同源)

值得一提的是,对于一段JavaScript脚本来说,其“源”与它存储的地址无关,而取决于脚本被加载的页面。比如我们在某个页面中通过如下所示的<script>标签引用了来源于不同地方(“http://www.artech.com/”和“http://www.jinnan.me/”)的两个JavaScript脚本,它们均与当前页面同源。实际上接下来介绍的基于JSONP跨域资源共享就是利用了这个特性。

1: <script src="http://www.artech.com/scripts/common.js"></script>

2: <script src="http://www.jinnan.me/scripts/utility.js"></script>

除了<script>标签,HTML还具有其它一些具有src属性的标签(比如<img>、<iframe>和<link>等),它们均具有跨域加载资源的能力,所以同源策略对它们不做限制。对于这些具有src属性的HTML标签来说,标签的每次加载都意味着针对目标地址的一次HTTP-GET请求。

同源策略以及跨域资源共享在大部分情况下针对的是Ajax请求。同源策略主要限制了通过XMLHttpRequest实现的Ajax请求,如果请求的是一个“异源”地址,浏览器将不允许读取返回的内容,我们可以通过一个简单的实例来演示这一点。
实例演示:跨域调用Web API

接下来我们通过于一个简单的实例来演示同源策略针对跨域Ajax请求的限制。如右图所示,我们利用Visual Studio在同一个解决方案中创建了两个Web应用。从项目名称可以看出,WebApi和MvcApp分别为ASP.NET Web API和MVC应用,后者是Web API的调用者。我们直接采用默认的IIS Express作为两个应用的宿主,并且固定了端口号:WebApi和MvcApp的端口号分别为“3721”和“9527”,所以指向两个应用的URI肯定不可能是同源的。

我们在WebApi应用中定义了如下一个继承自ApiController的ContactsController类型,它具有的唯一Action方法GetAllContacts返回一组联系人列表。由于具体返回的数据类型为JsonResult<IEnumerable<Contact>>,所以联系人 列表以JSON格式被序列化。

1: public class ContactsController : ApiController

2: {

3:     public IHttpActionResult GetAllContacts()

4:     {

5:         Contact[] contacts = new Contact[]

6:         {

7:             new Contact{ Name="张三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},

8:             new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},

9:             new Contact{ Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"},

10:         };

11:         return Json<IEnumerable<Contact>>(contacts);

12:     }

13: }

14:

15: public class Contact

16: {

17:     public string Name { get; set; }

18:     public string PhoneNo { get; set; }

19:     public string EmailAddress { get; set; }

20: }

接下来们在MvcApp应用中定义如下一个HomeController,默认的Action方法Index会将对应的View呈现出来。

1: public class HomeController : Controller

2: {

3:     public ActionResult Index()

4:     {

5:         return View();

6:     }

7: }

如下所示的是Action方法Index对应View的定义。我们的目的在于:当页面成功加载之后以Ajax请求的形式调用上面定义的Web API获取联系人列表,并将自呈现在页面上。如下面的代码片断所示,Ajax调用和返回数据的呈现是通过调用jQuery的getJSON方法完成的。

1: <html>

2: <head>

3:     <title>联系人列表</title>

4:     <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>

5: </head>

6: <body>

7:     <ul id="contacts"></ul>

8:     <script type="text/javascript">

9:         $(function ()

10:         {

11:             var url = "http://localhost:3721/api/contacts";

12:             $.getJSON(url, null, function (contacts) {

13:                 $.each(contacts, function (index, contact)

14:                 {

15:                     var html = "<li><ul>";

16:                     html += "<li>Name: " + contact.Name + "</li>";

17:                     html += "<li>Phone No:" + contact.PhoneNo + "</li>";

18:                     html += "<li>Email Address: " + contact.EmailAddress + "</li>";

19:                     html += "</ul>";

20:                     $("#contacts").append($(html));

21:                 });

22:             });

23:         }

24:         );

25:     </script>

26: </body>

27: </html>

如果运行我们的程序,我们将会得到如右图所示的空白页面,这就是“同源策略”导致的后果。值得一提的是,我们并不会得到任何的错误信息,这是因为大部分浏览器针对同源策略的支持都是隐性和透明的。如果开发人员对此不了解的话,根本想不明白错误根源何在。

如果我们采用Fiddler来监测页面加载过程中发送的请求和接收到的响应,我们会发现针对Web API调用的Ajax请求被成功发送,并且以JSON格式表示的联系人列表会被成功接收,请求和响应的内容如下所示。这实际上说明支持同源策略的浏览器其实并不会阻止跨域请求的发送和响应的接收,它仅仅是阻止程序获取和操作返回的数据而已。

1: GET http://localhost:3721/api/contacts HTTP/1.1

2: Host: localhost:3721

3: Connection: keep-alive

4: Cache-Control: max-age=0

5: Accept: application/json, text/javascript, */*; q=0.01

6: Origin: http://localhost:9527

7: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36

8: Referer: http://localhost:9527/

9: Accept-Encoding: gzip,deflate,sdch

10: Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh-TW;q=0.4

11:

12:

13: HTTP/1.1 200 OK

14: Cache-Control: no-cache

15: Pragma: no-cache

16: Content-Length: 205

17: Content-Type: application/json; charset=utf-8

18: Expires: -1

19: Server: Microsoft-IIS/8.0

20: X-AspNet-Version: 4.0.30319

21: X-SourceFiles: =?UTF-8?B?RTpc5oiR55qE6JGX5L2cXEFTUC5ORVQgV2ViIEFQSeahhuaetuaPreenmFxOZXcgU2FtcGxlc1xDaGFwdGVyIDE0XFMxNDAxXFdlYkFwaVxhcGlcY29udGFjdHM

22: X-Powered-By: ASP.NET

23: Date: Mon, 02 Dec 2013 01:47:53 GMT

24:

25: [{"Name":"张三","PhoneNo":"123","EmailAddress":"zhangsan@gmail.com"},{"Name":"李四","PhoneNo":"456","EmailAddress":"lisi@gmail.com"},{"Name":"王五","PhoneNo":"789","EmailAddress":"wangwu@gmail.com"}]

对于上面给出的针对Web API的Ajax请求的内容,我们可以看到它具有一个名为“Origin”的报头。该报头值表示请求页面的所在的站点(http://localhost:9527),它可以看成是浏览器对CORS(Cross-Origin Resource Sharing)规范的支持。
采用JSONP实现跨域资源共享

上面我们已经说过:JavaScript脚本的源决定于其被加载的页面,而不是其存储的地址。对于一段通过<script>标签的src属性加载的JavaScript脚本,它与当前页面同源。对于上面我们演示的实例来说,如果我们按照如下的方式来定义View:联系人列表的呈现单独定义在listContacts函数中(参数contacts表示联系人列表),并将Web API的地址置于<script>标签的src属性中来间接地调用它。

1: <html>

2: <head>

3:     <title>联系人列表</title>

4:     <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.10.2.js")"></script>

1:     <script type="text/javascript">

2:         function listContacts(contacts)

3:         {

4:             $.each(contacts, function (index, contact) {

5:                 var html = "<li><ul>";

6:                 html += "<li>Name: " + contact.Name + "</li>";

7:                 html += "<li>Phone No:" + contact.PhoneNo + "</li>";

8:                 html += "<li>Email Address: " + contact.EmailAddress + "</li>";

9:                 html += "</ul>";

10:                 $("#contacts").append($(html));

11:             });

12:         }

1:     </script>

2: </head>

3: <body>

4:     <ul id="contacts"></ul>

5:     <script type="text/javascript" src="http://localhost:3721/api/contacts?callback=listContacts"></script>

5: </body>

6: </html>

如果请求地址“http://localhost:3721/api/contacts?callback=listContacts”能够返回如下的内容,即返回的不是以JSON表示的数据,而是针对该数据的方法调用,毫无疑问联系人列表能够顺利呈现在页面上。这种将JSON对象填充(Padding)到某个JavaScript回调方法将数据转换成针对数据的操作语句的形式就是JSONP(JSON Padding)。

1: listContacts([{"Name":"张三","PhoneNo":"123","EmailAddress":"zhangsan@gmail.com"},{"Name":"李四","PhoneNo":"456","EmailAddress":"lisi@gmail.com"},{"Name":"王五","PhoneNo":"789","EmailAddress":"wangwu@gmail.com"}]);

为了让定义在ContactsController的Action方法GetAllContacts返回如上所示的内容,我们可以对其相应的改动来完成。如下面的代码片断所示,我们将GetAllContacts的返回类型替换成HttpResponseMessage,其参数callback表示填充的JavaScript回调函数。在该方法中,我们利用JavaScriptSerializer对Contact列表对象进行序列化,并将得到的内容填充到回调函数中从而得到如上所示的内容。方法最终返回具有此主体内容的HttpResponseMessage对象,响应主体内容的媒体类型被设置为“text/javascript”。

1: public class ContactsController : ApiController

2: {

3:     public HttpResponseMessage GetAllContacts(string callback)

4:     {

5:         Contact[] contacts = new Contact[]

6:         {

7:             new Contact{ Name="张三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},

8:             new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},

9:             new Contact{ Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"},

10:         };

11:         JavaScriptSerializer serializer = new JavaScriptSerializer();

12:         string content = string.Format("{0}({1})", callback, serializer.Serialize(contacts));

13:         return new HttpResponseMessage(HttpStatusCode.OK)

14:         {

15:             Content = new StringContent(content, Encoding.UTF8, "text/javascript")

16:         };

17:     }

18: }

如果现在运行我们的程序,通过“跨域”(其实不是)调用Web API得到的联系人列表就会按照如右图所示的效果呈现出来。JSONP仅仅是利用<script>的src标签加载的脚本不受同源策略约束而采取的一种编程技巧,其本身并不是一种官方协议。并且并非所有类型跨域调用都能采用JSONP的方式来解决(由于所有具有src属性的HTML标签均通过HTTP-GET的方式来加载目标资源,这决定了JSONP只适用于HTTP-GET请求),所以我们必须寻求一种更好的解决方案。
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

cors跨域资源共享】同源策略和jsonp相关推荐

  1. [CORS:跨域资源共享] 同源策略与JSONP

    Web API普遍采用面向资源的REST架构,将浏览器最终执行上下文的JavaScript应用Web API消费者的重要组成部分."同源策略"限制了JavaScript的跨站点调用 ...

  2. CORS跨域资源共享漏洞

    目录 同源策略 解决跨域问题的方案 CORS CORS原理 CORS漏洞攻击流程 CORS漏洞案例演示 CORS漏洞挖掘思考 漏洞危害 漏洞修复 跨域资源共享 (CORS) 是一种浏览器机制,可以对位 ...

  3. 09. ajax跨域问题,同源策略

    有三个标签允许跨域加载资源 <img src=""/> <link href=""/> <script src="&qu ...

  4. CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】

    每篇一句 重构一时爽,一直重构一直爽.但出了问题火葬场 前言 上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它.由于Java语言中的w ...

  5. 实现跨域访问---同源策略 、常见跨域方法

    实现跨域访问 同源策略 为了保证用户数据安全 防止恶意网站窃取数据 同源策略 三个行为限制: ​ Cookie.LocalStorage.indexDB无法读取 ​ DOM无法获取 ​ AJAX请求不 ...

  6. Python 使用CORS跨域资源共享解决flask服务器跨域问题、浏览器同源策略

    CORS 全称 Cross-origin resource sharing(跨域资源共享),只要服务端配置了 CORS,前端调用时就可以实现跨域访问了. 形式就是封装在 header 里的一些参数,例 ...

  7. php跨域资源共享,CORS 跨域资源共享

    CORS (Cross-Origin Resource Sharing) 跨域资源共享 为什么需要 CORS 首先,跨域指的是同一个域名下的资源,同时要注意域名与子域名,比如 developers.e ...

  8. tomcat7.0配置CORS(跨域资源共享)

    平时我们做前台页面时可能会遇到浏览器以下提示(浏览器控制台): 已阻止跨源请求:同源策略禁止读取位于 http://xxx.xxx.com 的远程资源.(原因:CORS 头缺少 'Access-Con ...

  9. Spring Boot CORS跨域资源共享实现方案

    同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能 同源策略限制cookie 等信息的跨源网页读取,可以保护本地用户信息 同源策略限制跨域 aja ...

最新文章

  1. Windows2003实用技巧
  2. 使用ueditor小结
  3. 求周期方波信号的傅里叶级数_1-1 求周期方波(见图1-4)的傅里叶级数(复指数函数形 ….doc...
  4. js控制图像等比例缩放
  5. 《动手学深度学习》TF2.0 实现
  6. cut\grep\awk\sed命令详解
  7. 关于软件测试学习的心得
  8. 【SCM】基于报童模型的MAPE与Profit仿真
  9. Linux终端快捷键的使用
  10. 天正电气T20 V6完全使用指南
  11. CCF试题 201903-2 二十四点解析
  12. 网络攻防技术——MD5碰撞试验
  13. 2022.6.28 JCR最新发布(期刊影响因子)
  14. matlab做瀑布图,Matlab画瀑布图,福利叶变换,频谱图代码
  15. 快学Big Data -- Hadoop(十三)
  16. Java实验——分别统计字符串中出现的大写字母、小写字母个数,以及出现的数字字符以及其他字符的个数
  17. reduceByKey
  18. Alpha策略 股票-股指对冲
  19. Python爬虫-Selenium(1)
  20. 使用keytool生成证书和秘钥

热门文章

  1. 转转二手交易平台建设高效率循环经济链
  2. 小明的调查作业java_小明的调查作业
  3. 中国空气质量在线监測分析平台
  4. php防止恶意刷新与刷票的方法
  5. QQ2013 协议分析
  6. 《炬丰科技-半导体工艺》化学蚀刻的铜-ETP铜
  7. 教你用html+js制作一个自己的点名系统,实例代码分享
  8. 价值规律的作用是什么
  9. LVS原理详解(4种工作模式)
  10. 找窗口的dataobject,creategroup,对window进行dataobject的赋值