美文网首页
常见的跨域解决方案

常见的跨域解决方案

作者: cfighter | 来源:发表于2017-07-30 12:01 被阅读0次

1、JSONP

受浏览器同源策略的限制,网页无法向其他域发送ajax请求,但在页面中引入其他域的脚本是可以的,最常见的例子就是在页面中引入cdn服务器上的js文件及图片等静态资源,JSONP正是利用这一特性实现了跨域。
例如,http://test.com/test.html获取http://abc.test.com/data.php上的数据,那么只需要在test.html中加入以下代码即可:

<script>
    function handleData(data){
        // do something
    }
</script>
<script scr="http://abc.test.com/data.php?callback=handleData"></script>

其实第二个标签返回的是一个可执行的js文件,data.php包含这样一段代码:

<?php
$callback = $_GET['callback']; 
$data = array(1,2);
echo $callback.'('.json_encode($data)')'
?>

当第二个标签加载完毕后,就会执行handleData([1,2])

2、document.domain

浏览器同源策略中第二个限制是不同域的框架之间不能进行js交互(但可获得彼此的window对象)
例如,在http://abc.test.com/test.html这个页面中有一个iframe起src为http://bcd.test.com/test2.html,以下代码会出现注释中的问题

//test.html
<script>
    function ifrLoad(){
        var iframe=document.getElementById('iframe');
        var ifrWin=iframe.contentWindow; //获得iframe的window对象(但属性和方法几乎不可用)
        console.log(ifrWin.document); //无法获得document属性
    }
</script>
<iframe src="http://bcd.test.com/test2.html" id="iframe" onload="ifrLoad()" ></iframe>

此时可通过document.domain设置当前文档的原始域实现跨域操作,只要两个页面的原始域相同,就可通过js获得iframe中的各种属性和方法了.

<!-- test.html   -->
<script>
   document.domain='test.com'
   function ifrLoad(){
       var iframe=document.getElementById('iframe');
       var ifrWin=iframe.contentWindow; //获得iframe的window对象(但属性和方法几乎不可用)
       console.log(ifrWin.document);  //正常
   }
</script>
<iframe src="https:www.baidu.com" id="iframe" onload="ifrLoad()" ></iframe>
<!-- test2.html -->
<script>
    document.domain='test.com'
</script>

需要要注意的是,d只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.test.com 中某个文档的document.domain 可以设成a.b.test.com、b.test.com 、test.com中的任意一个,但是不可以设成 c.a.b.test.com,因为这是当前域的子域,也不可以设成example.com,因为主域已经不相同了。

3 、window.name

window.name属性在不同的页面(甚至不同域名)加载后依旧存在(如果没修改则值不会变化),并且可以支持非常长的 name 值(2MB)假设我们在百度首页设置了window.name为'baidu',

我们在同一窗口地址栏中输入谷歌网址,此时我们查看window.name会发现window.name依然为‘baidu’

此时我们修改window.name为'google',再次打开百度,发现window.name变为了‘google’


了解了window.name属性之后,我们想要从test页面中获得test1中的数据就容易多了,可以首先加载test1页面,将test页面需要的数据存在window.name中,然后加载test页面,但貌似这种方式很蠢,解决办法是在test页面中设置一个隐藏的iframe标签用于获取test2页面的window.name,但需要注意的是受同源策略的限制,需要在iframe中的test2加载完毕后,在iframe中加载与test同源的test3页面。

<!-- http://abc.test.com/test.html   -->
<script>
    function loadData(){
        var iframe=document.getElementById('iframe');
        iframe.onload=fucntion(){
            var data=iframe.contentWindow.name
            console.log(data)
        }
        iframe.src='http://abc.test.com/test3.html'

    }
</script>
<iframe src="http://bcd.test.com/test2.html" id="iframe" onload="loadData()" ></iframe>

4、window.postMessage

window.postMessage是HTML5的API,允许跨域在两个窗口/frames之间发送数据。需要注意的是调用postMessage方法的window对象是指接受消息的那个window对象。其调用方式如下:

otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow 是其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
argetOrigin 是用来接收消息的那个window对象所在的域,如果不希望做限定,可以用*代替。
transfer 可选,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

<!-- http://abc.test.com/test.html   -->
<script>
    function ifrLoad(){
        var iframe=document.geElementById('iframe');
        iframe.contentWindow.postMessage('hello world!','*')
    }
</script>
<iframe src="http://bcd.test.com/test2.html" id="iframe" onload="ifrLoad()" '></iframe>
<!-- test2.html -->
<script>
    window.onmessage=function(e){
        console.log(e.data)
    }
</script>

5 、跨域资源共享(CORS)

服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求,但需要浏览器需要支持HTML5,可以支持POST,PUT等方法

HTML5标准中提出的跨域资源共享(Cross Origin Resource Share,CORS)支持其他的HTTP方法如PUT, POST等,可以从本质上解决跨域问题。
例如,从http://a.com要访问http://b.com的数据,通常情况下Chrome会因跨域请求而报错:

XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access.

错误原因是被请求资源没有设置Access-Control-Allow-Origin,所以我们在b.com的服务器中设置这个响应头字段即可:

Access-Control-Allow-Origin: * # 允许所有域名访问,或者
Access-Control-Allow-Origin: http://a.com # 只允许所有域名访问

为 xhr设置 withCredentials后CORS方法跨域还可携带Cookie,但 PUT/POST 请求需要注意处理 preflight 请求

6、Proxy

可以在服务器端设置一个代理,由服务器端向跨域下的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制。

相关文章

  • 跨域

    博客 说说跨域那些事儿 不要再问我跨域的问题了 前端常见跨域解决方案(全) 同源策略 JSONP(填充式JSON)...

  • 常见跨域解决方案

    目前常见的跨域解决方案 Jsonp最早的解决方案,利用script标签可以跨域的原理实现限制: 需要服务的支持 只...

  • 前端常见跨域解决方案(全)

    前端常见跨域解决方案(全) 什么是跨域? 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的...

  • js常见跨域解决方案

    参考:前端常见跨域解决方案(全) 跨域,什么是“域”? 这里就要先说说同源策略了。所谓同源是指"协议+域名+端口"...

  • 前端不同的跨域方案总结

    做个收录,方便以后复盘。本文转自:前端常见跨域解决方案(全)。 什么是跨域? 跨域是指一个域下的文档或脚本试图去请...

  • JWT简介

    前言 JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。微服务常见的认证方案 一、跨域认证...

  • 常见跨域解决方案以及Ocelot 跨域配置

    常见跨域解决方案以及Ocelot 跨域配置 Intro 我们在使用前后端分离的模式进行开发的时候,如果前端项目和a...

  • JS知识点

    1、前端常见跨域解决方案 2、cookie,localStorage,SessionStorage三者的区别 3、...

  • 跨域的几种解决方案

    跨域是web开发中经常会遇到的情况,只出现在浏览器端。本文列举了一些常见的跨域情况,和解决方案。 什么是跨域,为什...

  • 跨域解决方案

    收集整理了常见跨域解决方案,欢迎补充指正。 通过jsonp跨域 通常为了减轻web服务器的负载,我们把js、css...

网友评论

      本文标题:常见的跨域解决方案

      本文链接:https://www.haomeiwen.com/subject/lumhbttx.html