美文网首页
JSONP,跨域

JSONP,跨域

作者: 湖衣 | 来源:发表于2017-08-22 14:54 被阅读0次

    JSONP、跨域是面试必问问题之一
    困难在于脑海里认为一个ajax请求的结果是一个json或XML
    如果不用ajax请求

    json内容不是固定的,传什么给什么

    }else if(path === '/main.js'){  
        var string = fs.readFileSync('./main.js', 'utf8')
        response.setHeader('Content-Type', 'application/javascript')
        response.end(string.replace('%xxx%', query.content))
      }else{
    

    jsonp = json+padding
    发一个请求,服务器根据请求参数返回js,js插入页面,被执行

    如果js所在的源与要请求的源不一样,浏览器会拒绝把响应给js

    CORS

    只要JS请求的源在响应里加上
    :<JS所在的源>

    状态码
    2xx 一切安好
    3xx 滚 301:滚到另外一个地址上去 302:
    4xx 你错了
    5xx 我错了
    200 ok
    204 新建成功

    403:没有权限访问
    404:没有找到

     btn.onclick = function(){
        var number = parseInt(Math.random() * 10000000,10)
        var functionName = 'jQuery'+ number
    
        window[functionName] = function(data){
          console.log(data)
        }
    
        var script = document.createElement('script')
        var value = document.querySelector('#xxx').value
        script.src = '/main.js?content=' + functionName 
        document.body.appendChild(script)
      }
    
     btn.onclick = function(){
        jsonp('/main.js', 'content')
      }
    
      function jsonp(url, param){
        var number = parseInt(Math.random() * 10000000,10)
        var functionName = 'jQuery'+ number
    
        window[functionName] = function(data){
          console.log(data)
        }
    
        var script = document.createElement('script')
        var value = document.querySelector('#xxx').value
        script.src = url + '?'+ param + '=' + functionName 
        document.body.appendChild(script)
      }
    

    题目1: 什么是同源策略
    浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。本域指的是同协议,同域名,同端口。

    题目2: 什么是跨域?跨域有几种实现形式。
    1.JSONP
    例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。

    function getData(data){
        //这里是对获取的数据的相关操作
        console.log(data);
        //数据获取到后移除创建的script标签
        document.body.removeChild(originData);
    }
    var originData = document.createElement('script');
    originData.src = 'http://www.jesse.com/data.js';
    originData.setAttribute("type", "text/javascript");
    document.body.appendChild(originData);
    

    2.CORS
    跨源资源共享(CORS)定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。它只要JS请求的源在响应里加上Access-Control-Allow-Origin:<JS所在的源>。

    3.降域
    对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。 具体的做法是可以在http://www.a.com/a.htmlhttp://script.a.com/b.html两个文件中分别加上 document.domain = "a.com";然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以 “交互”了。

    4.postMessage
    window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

    JSONP是针对接口的,CORS是针对域名的有可能会遭到XSS攻击,CORS在IE8上的兼容性不好,偶尔调用的话就可以选JSONP

    题目3: JSONP 的原理是什么?
    1.页面上调用js文件时不受跨域的影响,而且,凡是拥有src属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>。
    2.可以在远程服务器上设法把数据装进js格式的文件里,供客户端调用处理,实现跨域。
    3.目前最常用的数据交换方式是JSON,客户端通过调用远程服务器上动态生成的js格式文件(一般以JSON后缀)。
    4.客户端成功调用JSON文件后,对其进行处理。
    5.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

    题目4: CORS是什么?
    CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
    简单请求
    某些请求不会触发 CORS 预检请求,本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:
    使用下列方法之一:GET , HEAD , POST
    预检请求
    与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

    题目5: 根据视频里的讲解演示三种以上跨域的解决方式。
    JSONP:
    index.html

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
    </head>
    <body>
      <div class="container">
          <ul class="news">
            <li>第11日前瞻:中国冲击4金 博尔特再战</li>
            <li>男双力争会师决赛 </li> 
            <li>女排将死磕巴西!</li>
          </ul>
          <button class="change">换一组</button>
      </div>
      <script>
        $('.change').addEventListener('click', function(){
          var script = document.createElement('script');
          script.src = 'http://b.jrg.com:8080/getNews?callback=appendHtml';
          document.head.appendChild(script);
          document.head.removeChild(script);
        })
        
        function appendHtml(news){
          var html = '';
          for( var i=0; i<news.length; i++){
            html += '<li>' + news[i] + '</li>';
          }
          $('.news').innerHTML = html;
        }
        
        function $(id){
          return document.querySelector(id);
        }
      </script>  
    </body>
    </html>
    

    router.js

    app.get('/getNews', function(req, res){
        var news = [
            "第11日前瞻:中国冲击4金 博尔特再战200米羽球",
            "正直播柴飚/洪炜出战 男双力争会师决赛",
            "女排将死磕巴西!郎平安排男陪练模仿对方核心",
            "没有中国选手和巨星的110米栏 我们还看吗?",
            "中英上演奥运金牌大战",
            "博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多",
            "最“出柜”奥运?同性之爱闪耀里约",
            "下跪拜谢与洪荒之力一样 都是真情流露"
        ]
        var data = [];
        for(var i=0; i<3; i++){
            var index = parseInt(Math.random()*news.length);
            data.push(news[index]);
            news.splice(index, 1);
        }
        var cb = req.query.callback;
        if(cb){
            res.send(cb + '('+ JSON.stringify(data) + ')');
        }else{
            res.send(data);
        }
        
    })
    

    CORS
    index.html

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
    </head>
    <body>
      <div class="container">
          <ul class="news">
            <li>第11日前瞻:中国冲击4金 博尔特再战</li>
            <li>男双力争会师决赛 </li> 
            <li>女排将死磕巴西!</li>
          </ul>
          <button class="change">换一组</button>
      </div>
      <script>
        $('.change').addEventListener('click', function(){
            var xhr = new XMLHttpRequest();
            xhr.open('get', 'http://b.jrg.com:8080/getNews', true );
            xhr.send();
            xhr.onreadystatechange = function (){
                if (xhr.readyState === 4 && xhr.readyState === 200){
                    appendHtml(JSON.parse(xhr.responseText))
                }
            }
        })
        
        function appendHtml(news){
          var html = '';
          for( var i=0; i<news.length; i++){
            html += '<li>' + news[i] + '</li>';
          }
          $('.news').innerHTML = html;
        }
        
        function $(id){
          return document.querySelector(id);
        }
      </script>  
    </body>
    </html>
    

    router.js

    app.get('/getNews', function(req, res){
        var news = [
            "第11日前瞻:中国冲击4金 博尔特再战200米羽球",
            "正直播柴飚/洪炜出战 男双力争会师决赛",
            "女排将死磕巴西!郎平安排男陪练模仿对方核心",
            "没有中国选手和巨星的110米栏 我们还看吗?",
            "中英上演奥运金牌大战",
            "博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多",
            "最“出柜”奥运?同性之爱闪耀里约",
            "下跪拜谢与洪荒之力一样 都是真情流露"
        ]
        var data = [];
        for(var i=0; i<3; i++){
            var index = parseInt(Math.random()*news.length);
            data.push(news[index]);
            news.splice(index, 1);
        }
        
        res.header("Access-Control-Allow-Origin", "http://a.jrg.com:8080");
        res.send(data);
    })
    

    postMessage
    a.html

    <!DOCTYPE html>
    <html>
    <head>  
        <meta charset="utf-8">
        <style>
        .ct{
          width: 910px;
          margin: auto;
        }
        .main{
          float: left;
          width: 450px;
          height: 300px;
          border: 1px solid #ccc;
        }
        .main input{
          margin: 20px;
          width: 200px;
        }
        .iframe{
          float: right;
        }
        iframe{
          width: 450px;
          height: 300px;
          border: 1px dashed #ccc;
        }
      </style>
    </head>
    <body>
        <div class="ct">
            <h1>postMessage</h1>
            <div class="main">
                <input type="text" placeholder="http://a.jrg.com:8080/a.html">
            </div>
            <iframe src="http://b.jrg.com:8080/b.html" frameborder="0" ></iframe>
        </div>
        
        <script>
            $('.main input').addEventListener('input', function(){
            console.log(this.value);
            window.frames[0].postMessage(this.value,'*');
            })
            window.addEventListener('message',function(e) {
                    $('.main input').value = e.data
                console.log(e.data);
            });
            function $(id){
                return document.querySelector(id);
            }
        </script>
    </body>
    </html>
    

    b.html

    <!DOCTYPE html>
    <html>
    <head>  
        <meta charset="utf-8">
        <style>
            html,body{
                margin: 0;
            }
            input{
                margin: 20px;
                width: 200px;
            }
        </style>
    </head>
    <body>
        <input id="input" type="text"  placeholder="http://b.jrg.com:8080/b.html">
        
        <script>
            $('#input').addEventListener('input', function(){
                window.parent.postMessage(this.value, '*');
            })
            window.addEventListener('message',function(e) {
                $('#input').value = e.data
                console.log(e.data);
            });
            function $(id){
                return document.querySelector(id);
            }
        </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:JSONP,跨域

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