跨域问题6种解决方式

为什么会有跨越问题?
因为所有支持Javascript的浏览器都会使用同源策略这个安全策略。

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。
所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当一个百度浏览器
执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
下面介绍5种解决跨域的方法
1. 通过jsonp跨域

利用页面上可以引入不同域上的js脚本文件。步骤如下:
1. 浏览器端注册callback回调函数。
2. 然后动态生成一个 script 标签,src 为:请求资源的地址+获取函数的字段名+回调函数名称。
3. 让服务端拿到回调函数名称,填充数据返回一段js代码给浏览器
4. 浏览器执行
具体代码:

function resolveJosn(result) { //浏览器端代码
    console.log(result.name);
}
var jsonpScript= document.createElement("script");
jsonpScript.type = "text/javascript";
jsonpScript.src = "http://www.qiute.com?    
callbackName=resolveJson";
document.getElementsByTagName("head")[0].appendChild(jsonpScript);

php //服务器端代码
<?php
    $callback = $_GET['callback'];  // 获取回调函数名
    $arr = array("name" => "alsy", "age" => "20"); // 要请求的数据
    echo $callback."(". json_encode($arr) .");"; // 输出
?>
2. 通过修改document.domain来跨子域(iframe)

特点:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致。
使用方法:document.domain 的设置是有限制的,我们只能把 document.domain 设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的 document.domain 可以设成a.b.example.com、b.example.com、example.com中的任意一个,但是不可以设成c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。
具体代码:
// 主页面:http://blog.qiutc.me/a.html
<script>
document.domain = 'qiutc.me';

function onLoad() {
    var iframe = document.getElementById('iframe');
    var iframeWindow = iframe.contentWindow; // 这里可以获取 iframe 里面 window 对象并且能得到方法和属性
    var doc = iframeWindow.document; // 获取到
    iframeWindow.getData('http://www.qiutc.me/json_domain.php', '{u: "alsy-domain", age: "20"}', function(r) {
        console.log(eval("(" + r + ")"));
    });
} //由于json_domain.php与下面的框架同域,所以可以这样通过子域获取数据
</script>
<iframe src="http://www.qiutc.me/b.html" onload="onLoad()" </iframe>
    // iframe 里面的页面(在另一个文件中)
    <script>
    document.domain = 'qiutc.me';
    window.getData = function(url, data, cb) {
        var xhr = null;
        if (window.XMLHttpRequest) {
            xhr = new XMLHttpRequest();
        } else {
            xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }
        xhr.open('POST', url, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4 && xhr.status === 200) {
                cb(xhr.responseText);
            }
        }
        xhr.send(data);
    }
    </script>
3. 隐藏的iframe+window.name跨域

原理:window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name 的,每个页面对 window.name 都有读写的权限,window.name 是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

比如有一个www.sdc.me/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.baidu.com/data.html里的数据。步骤:
1.把a。html里的iframe的src设为www.baidu/data.html
2.iframe的src设成跟a.html页面同一个域才行,这样才符合同源策略。

www.baidu.com/data.html 代码如下:

 <script>
     window.name = '我是被期望得到的数据';
 </script>

在 a.html 页面中使用一个隐藏的 iframe 来充当一个中间人角色,由 iframe 去获取 data.html 的数据,然后 a.html 再去得到 iframe 获取到的数据。代码如下:

// a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
function getData() {
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = iframe.contentWindow.name; // 得到
    }
    iframe.src = 'b.html'; // 这里b和a同源
}
</script>
</head>
<body>
<iframe src="http://www.baidu.com/data.html" style="display:none" onload="getData()" </iframe>
</body>
</html>
4.frame+跨文档消息传递

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源.
步骤:

  1. 调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。

  2. 需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

    // 主页面 blog.qiutc.com
     <script>
     function onLoad() {
         var iframe = document.getElementById('iframe');
         var iframeWindow = iframe.contentWindow;
         iframeWindow.postMessage("I'm message from main page.");
     }
     </script>
     <iframe src="http://www.qiutc.me/b.html" onload="onLoad()" </iframe>
         // b 页面
         <script>
         window.onmessage = function(e) {
             e = e || event;
             console.log(e.data);
         }
         </script>
    
5.跨域资源共享 CORS
  1. 服务器响应头:Access-Control-Allow-Origin它的值设置成 *,表示接受任意域名的请求。
  2. 如果要发送Cookie,Access-Control-Allow-Origin就不能设为*,必须指定明确的、与请求网页一致的域名。
6. WebSockets

HTML5新增的一大特性之一就是: Web Sockets 其目标是在一个单独的持久连接上提供全双工、双向通信。在 JavaScript 中创建了 Web Socket 之后,会有一个HTTP 请求发送到浏览器以发起连接。在取得服务器响应后,建立的连接会使用 HTTP 升级从 HTTP 协议交换为 WebSocket 协议。也就是说,使用标准的 HTTP 服务器无法实现 Web Sockets,只有支持这种协议的专门服务器才能正常工作。
同源策略对 Web Sockets 不适用,因此可以通过它打开到任何站点的连接。至于是否会与某个域中的页面通信,则完全取决于服务器。(通过握手信息就可以知道请求来自何方。)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容

  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    他在发呆阅读 820评论 0 0
  • 什么是跨域? 2.) 资源嵌入:、、、等dom标签,还有样式中background:url()、@font-fac...
    电影里的梦i阅读 2,350评论 0 5
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    w_zhuan阅读 503评论 0 0
  • 跨域问题产生的原理是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js...
    往复随安_cc75阅读 508评论 0 1
  • 如果政策可以放开,可以允许你做你自己想做的事,这个世界上没有钱的存在,整个地球的人们都有同一个梦想,是探索宇宙...
    无病a阅读 194评论 3 6