zoukankan      html  css  js  c++  java
  • JS 跨域认识及如何解决

    什么是跨域

    指的是浏览器不允许javascrip脚本向其他域名发起ajax请求。

    跨域的各种情况判定

    URL                      说明       是否允许通信
    http://www.a.com/a.js
    http://www.a.com/b.js     同一域名下   允许
    http://www.a.com/lab/a.js
    http://www.a.com/script/b.js 同一域名下不同文件夹 允许
    http://www.a.com:8000/a.js
    http://www.a.com/b.js     同一域名,不同端口  不允许
    http://www.a.com/a.js
    https://www.a.com/b.js 同一域名,不同协议 不允许
    http://www.a.com/a.js
    http://70.32.92.74/b.js 域名和域名对应ip 不允许
    http://www.a.com/a.js
    http://script.a.com/b.js 主域相同,子域不同 不允许
    http://www.a.com/a.js
    http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
    http://www.cnblogs.com/a.js
    http://www.a.com/b.js 不同域名 不允许

    解决办法:

    JSONP

    <script> 标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。

    所以 JSONP 的理念就是,我和服务端约定好一个函数名,当我请求文件的时候,服务端返回一段 JavaScript。这段 JavaScript 调用了我们约定好的函数,并且将数据当做参数传入。非常巧合的一点(其实并不是),JSON 的数据格式和 JavaScript 语言里对象的格式正好相同。所以在我们约定的函数里面可以直接使用这个对象。

    光说不练假把式,让我们来看一个例子:

    你需要获取数据的页面 index.html:

    <script>
        function getWeather(data) {
            console.log(data);
        }
    </script>
    
    <script src="http://x.y.com/xx.js">

    http://x.y.com/xx.js 文件内容:

     
    getWeather({
        "城市": "北京",
        "天气": "大雾"
    });

    我们可以看到,在我们定义了 getWeather(data) 这个函数后,直接载入了 xx.js。
    在这个脚本中,执行了 getWeather 函数,并传入了一个对象。然后我们在这个函数中将这个对象输出到 console 中。

    这就是整个 JSONP 的流程。

    跨资源共享(CORS)

    通过修改document.domain来跨子域

    浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。
    不同的框架之间是可以获取window对象的,但却无法获取相应的属性和方法。比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

    <script type="text/javascript">
        function test(){
            var iframe = document.getElementById('ifame');
            var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的
            var doc = win.document;//这里获取不到iframe里的document对象
            var name = win.name;//这里同样获取不到window对象的name属性
        }
    </script>
    <iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
    

    这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。

    1.在页面 http://www.example.com/a.html 中设置document.domain:

    <iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
    <script type="text/javascript">
        document.domain = 'example.com';//设置成主域
        function test(){
            alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
        }
    </script>
    

    2.在页面 http://example.com/b.html 中也设置document.domain:

    <script type="text/javascript">
        document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
    </script>
    

    修改document.domain的方法只适用于不同子域的框架间的交互。

    使用window.name来进行跨域

    window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的

    使用HTML5的window.postMessage方法跨域

    在 HTML5 中, window 对象增加了一个非常有用的方法:

    windowObj.postMessage(message, targetOrigin);
    • windowObj: 接受消息的 Window 对象。

    • message: 在最新的浏览器中可以是对象。

    • targetOrigin: 目标的源,* 表示任意。

    这个方法非常强大,无视协议,端口,域名的不同。下面是烤熟的栗子:

    var windowObj = window; // 可以是其他的 Window 对象的引用
    var data = null;
    
    addEventListener('message', function(e){
        if(e.origin == 'http://jasonkid.github.io/fezone') {
            data = e.data;
            
            e.source.postMessage('Got it!', '*');
        }
    });

    message 事件就是用来接收 postMessage 发送过来的请求的。函数参数的属性有以下几个:

    • origin: 发送消息的 window 的源。

    • data: 数据。

    • source: 发送消息的 Window 对象。

    引用:

    https://segmentfault.com/a/1190000000718840

    https://segmentfault.com/a/1190000003642057

  • 相关阅读:
    jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解
    jQuery 源码解析(二十三) DOM操作模块 替换元素 详解
    jQuery 源码解析(二十二) DOM操作模块 复制元素 详解
    jQuery 源码分析(二十一) DOM操作模块 删除元素 详解
    jQuery 源码分析(二十) DOM操作模块 插入元素 详解
    jQuery 源码分析(十九) DOM遍历模块详解
    python 简单工厂模式
    python 爬虫-协程 采集博客园
    vue 自定义image组件
    微信小程序 image组件坑
  • 原文地址:https://www.cnblogs.com/linyihai/p/7172057.html
Copyright © 2011-2022 走看看