跨域问题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 不适用,因此可以通过它打开到任何站点的连接。至于是否会与某个域中的页面通信,则完全取决于服务器。(通过握手信息就可以知道请求来自何方。)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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