美文网首页
JSONP&跨域

JSONP&跨域

作者: D一梦三四年 | 来源:发表于2017-10-10 12:25 被阅读0次

    1. 什么是同源策略

    • 同源指的是网页的协议、域名和端口都相同,不同源的客户端脚本在没明确授权的情况下,不能读写对方的资源。
    • 同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
    • 随着互联网的发展,现主要有三种行为受到同源策略的限制:
      • Cookie、LocalStorage 和 IndexDB 无法读取。
      • DOM 无法获得。
      • 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
    同一域名,不同二级域名(同上) 不允许
    http://www.cnblogs.com/a.js
    http://www.a.com/b.js
    不同域名 不允许

    2. 什么是跨域,跨域有几种实现形式?

    • 跨域:为了获取不同源网页上的图片、脚本等资源,我们就需要跨域了。
    • 跨域的方式
      • JSONP
      • CORS
      • WebSocket
      • postMessage
      • window.name
      • document.domain

    3. JSONP 的原理是什么?

    • JSONP即 JSON with padding(填充式JSON或参数式JSON),是被包含在函数调用中的JSON,如callback({ "name": "xiaoming"})
    • JSONP是通过动态 <script> 元素来使用的,使用时可为 src 属性制定一个跨域URL,<script> 与 <img> 标签类似,都具有不受限制的从其它域加载资源的能力。因为JSONP是有效的 JavaScript 代码,在请求完成后,即JSONP响应加载到页面中以后,就会马上执行。
    • JSONP分两部分组成:回调函数和数据。回调函数是当响应到来时,应该在页面调用的函数,回调函数的名字一般是在请求中指定的;而数据就是传入回调函数中的JSON数据。如:http://www.a.com/?callback=handleResponse

    4. CORS是什么?

    • CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS背后的基本思想,就是使用自定义的HTTTP头部让浏览器与服务器进行沟通,从而决定响应是成功还是失败。CORS需要浏览器和服务器同时支持,支持现代浏览器,IE支持10以上。
    • 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的 Ajax 通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该响应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 Ajax 请求没啥区别,代码完全一样。
    • 因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

    5. 跨域的解决方式

    JSONP:利用<script>标签没有跨域限制来达到与第三方通讯的目的。

    1. 创建 index.html
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>Messages</title>
    </head>
    <body>
        <ul class="messages"></ul>
    
    <script>
        var script = document.createElement('script');
        script.src = 'http://localhost:8080/getMessages?name=小明&callback=searchMessage';
        document.head.appendChild(script);
        document.head.removeChild(script);
    
        function searchMessage(person) {
            var html = '';
            for (var i = 0; i < person.length; i++) {
                html += '<li>' + person[i] + '</li>';
            }
            console.log(html);
            $('.messages').innerHTML = html;
        }
    
        function $(id) {
            return document.querySelector(id);
        }
    </script>
    </html>
    
    1. 创建 router.js
    router.get('/getMessages', function (req, res) {
        var name = req.query.name;
        var messages = [];
        if (name === '小明') {
            messages.push("name: 小明", "age: 23")
        } else if (name === '小李') {
            messages.push("name: 小李", "age: 20")
        } else {
            return;
        }
    
        var cb = req.query.callback;
        if (cb) {
            res.send(cb + '(' + JSON.stringify(messages) + ')');
        } else {
            res.send(messages);
        }
    })
    
    1. 打开本地服务器


      本地服务器.png
    2. 打开另外一个端口


      JSONP.png

    CORS:在HTTP请求里添加特殊的头,允许服务器指定特定的域名可以跨域访问。

    1. 创建 index.html
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>Messages</title>
    </head>
    <body>
    <button class="btn">获取信息</button>
    <p class="messages"></p>
    <script>
        var btn = document.querySelector('.btn');
        var messages = document.querySelector('.messages');
        btn.addEventListener('click', function () {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200 || xhr.status === 304) {
                        var results = JSON.parse(xhr.responseText);
                        messages.innerText += '姓名:' + results.name;
                    }
                }
            }
            xhr.open('GET', 'http://localhost:8080/getMessages?name=小明', true);
            xhr.send();
        })
    </script>
    </html>
    
    1. 创建 router.js
    router.get('/getMessages', function (req, res) {
        res.header('Access-Control-Allow-Origin', '*');
        var name = req.query.name;
        var data = {};
        if (name === '小明') {
            data = {name: "小明"}
        } else if (name === '小李') {
            data = {name: "小李"}
        } else {
            return;
        }
        res.send(data);
    })
    
    1. 打开本地服务器


      本地服务器.png
    2. 打开另外一个端口
    CORS.png

    postMessage:允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

    1. 创建 index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>A</title>
    </head>
    <body>
    <input id="inta" type="text" placeholder="aaa">
    <p>我是A窗口</p>
    <iframe src="http://192.168.0.248:8080/xxx.html" width="300px" height="200px" style="border: 1px dotted"></iframe>
    <script type="text/javascript">
        var btna = document.getElementById('inta')
        btna.oninput = function(){
            window.frames[0].postMessage(this.value,'*')
        }
        window.addEventListener('message',function(e){
            btna.value.e.data
        })
    </script>
    </body>
    </html>
    
    1. 创建 xxx.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>B</title>
    </head>
    <body>
    <input id="intb" type="text" placeholder="bbb">
    <p>我是B窗口</p>
    <script type="text/javascript">
        var btnb = document.getElementById('intb')
        btnb.oninput = function(){
            window.parent.postMessage(this.value,'*')
        }
        window.addEventListener('message',function(e){
            btnb.value=e.data
        })
    </script>
    </body>
    </html>
    
    1. 打开另外一个端口


      http-server.png
    2. 本地服务器


      postMessage.png

    相关文章

      网友评论

          本文标题:JSONP&跨域

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