javaScript_跨域资源共享CORS

要记录好这个问题,首先需要描述清楚这个问题。
有如下的一个场景:我们在实现一个系统中某个功能的时候,可能系统的某些模块不在一个域名下。用户中心模块部署在user.xxx.com下,产品相关的功能部署在product.xxx.com下,在用户中心的某些页面,我们或许要请求产品功能模块的功能,此时就会有问题出现。以Google Chrome(版本 45.0.2454.101 m)浏览器为例,当当前的页面在A域名下,我们在页面中构造了一个异步请求,我们需要调用位于B域名下的某个API,代码片段如下:
<script type="text/javascript">
    $(function() {
        //当前页面所在域名:http://localhost:9000/
        //jQuery版本:jquery-1.11.3.min.js
        $.ajax({
            url : "http://localhost:9001/order/pindexpost",
            type : "POST",
            dataType : 'json',
            success : function(data) {
                alert(data);
            }
        });
    });
</script>
但是请求之后,浏览器控制台给出了如下的错误信息

那么这就是标题中所提到的跨域资源共享CORS问题了。我们把这个概念细化一下,首先,为什么会有CORS?简单点理解就是出于安全考虑,浏览器都遵循一个叫同源策略的东西,他约束浏览器说“不是你的东西,你问人家要,人家默认不给你,除非人家同意给你”,基于这个策略,就有了跨域资源共享的问题,那么,怎么就叫跨域了呢?上面代码中的域名不是一样的吗,都是指向本地的localhost啊。举个栗子说明下

http://www.blogjava.net:80,左边是一个完整的请求,包含了协议,子域名等等若干部分,我们把它理解为域,但凡是在这个域下发生的请求,都无法直接访问到其他域的资源
  • http://www.blogjava.net:80能访问http://www.blogjava.net:81下的资源吗?不行!
  • http://www.blogjava.net:80能访问http://abc.blogjava.net:80下的资源吗?不行!
  • http://www.blogjava.net:80能访问https://www.blogjava.net:80下的资源吗?不行!
  • http://www.blogjava.net:80能访问http://域名对应的真实IP:80下的资源吗?不行!
  • http://www.blogjava.net:80能访问http://www.xyz.net:80下的资源吗?不行!
域哪怕有一点点不一样一点点不一样一点点不一样,都是不可以访问的,那么问题来了,如何实现跨域呢? 目前有三种方案可以打破同源策略所带来的限制,实现跨域请求。
  1. 使用JSONP。这种方案是使用HTML的script标签来实现的,script标签的src属性不受同源策略约束,可以访问任意站点的资源,但是,该方案有着自己的约束。首先,他只能发出GET请求,因为script标签的初衷就是为了获取js脚本,所以如果返回的数据内容不是js脚本的话,也不会成功。基于这个约束,我们需要改造一下我们的请求:
     1 <script type="text/javascript">
     2     $(function () {
     3     //当前页面所在域名:http://localhost:9000/
     4     // jQuery版本:jquery-1.11.3.min.js
     5         $.ajax({
     6             url: "http://localhost:9001/order/pindexpost",
     7             type: "POST", dataType: 'jsonp',
     8             jsonpCallback: "callback"
     9         });
    10     })
    11     ;
    12     function callback(result) {
    13         alert("suc:" + result);
    14     }
    15 </script> 
    刚才提到,JSONP方式是基于script标签的,所以我们要对返回的数据做一些处理,使返回的数据是一段js脚本才可以。我们在客户端预定义好callback函数,使得服务端返回数据的时候可以直接调用这个callback函数,服务端代码片段如下:
    1 response().setContentType("application/javascript");
    2 return ok("callback(" + data + ")");
    要注明返回的格式,并且data的格式也要符合js的语法。其实说白了,JSONP就是请求目标数据,然后将目标数据和回调函数进行拼接,以javascript的形式返回给浏览器,之后浏览器执行的这个回调函数。
  2. 使用代理服务器。这个比较好理解,不过运维的成分多一些,设置一个代理服务器,根据请求API所在命名空间的不同,转发到相应的域去,这样一来就骗过了浏览器,让浏览器以为所有的数据都来自一个域。
  3. 设置请求的相应头。在目标API的响应头中添加“Access-Control-Allow-Origin”,设置值为“*”,这就是让服务器通知浏览器,说“我这个API的响应,是面向所有人的,*就代表这个意思啊”,但是,这也会带来一个安全性的问题,所以你可以设置部分站点可以跨域访问,比如Access-Control-Allow-Origin: http://www.blogjava.net/,但是这个响应头存在一定的兼容问题,具体支持情况可以查看caniuse.com

posted on 2015-11-26 16:46 都较瘦 阅读(136) 评论(0)  编辑  收藏 所属分类: JavaScript案例积累


只有注册用户登录后才能发表评论。


网站导航:
 
<2015年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

导航

统计

公告

博客定位:囿于目前的水平,博客定位在记录自己的学习心得和随手的练习

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜