美文网首页
进阶13 JSONP 跨域

进阶13 JSONP 跨域

作者: 饥人谷_哈噜噜 | 来源:发表于2018-04-23 00:03 被阅读0次
    题目1: 什么是同源策略

    浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

    • 本域指的是?
      同协议:如都是http,https,file,ssh,mailto,tel
      同域名:如都是http://jirengu.com/ahttp://jirengu.com/b
      同端口:如都是80端口
    • 不同源的例子:
      http://jirengu.com/main.jshttps://jirengu.com/a.php(协议不同)
      http://jirengu.com/main.jshttp://bbs.jirengu.com/a.php (域名不同,域名必须完全相同才可以)
      http://jiengu.com/main.jshttp://jirengu.com:8080/a.php(端口不同,第一个是80)
      http://jiengu.com/main.jshttp://jiengu.com.cn/main.js
    题目2: 什么是跨域?跨域有几种实现形式
    • 跨域:突破同源策略的限制,允许不同域的接口进行交互
    • 实现形式:
      1. JSONP
      2. CORS
      3. 降域
      4. postMessage
    题目3: JSONP 的原理是什么

    利用<script>标签的可跨域性,基本思想是:

    1. 网页通过添加一个<script>标签,加载数据的方式去获取数据当做 JS 代码来执行,这种做法不受同源政策限制;
    2. 提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后在原始数据上「包裹」这个函数名,发送给前端。

    JSONP 需要对应接口的后端的配合才能实现。

    题目4: CORS是什么

    CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。

    1. 前端用 XMLHttpRequest跨域访问时,浏览器会在请求头中添加:origin
    2. 后端会添加一个响应头:Access-Control-Allow-Origin
    3. 浏览器判断该相应头中Access-Control-Allow-Origin的值是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
    题目5: 根据视频里的讲解演示三种以上跨域的解决方式 ,写成博客
    • JSONP
      index.html
    <!DOCTYPE html>
    <html>
      <body>
        <div class="container">
          <ul class="news">
          </ul>
          <button class="show">show news</button>
        </div>
    
      <script>
        $('.show').addEventListener('click', function(){
          var script = document.createElement('script');//添加script标签
          script.src = 'http://127.0.0.1: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>';
          }
          console.log(html);
          $('.news').innerHTML = html;
        }
        function $(id){
          return document.querySelector(id);
        }
      </script>
    
    </html>
    

    server.js

    var http = require('http')
    var fs = require('fs')
    var path = require('path')
    var url = require('url')
    
    http.createServer(function(req, res){
      var pathObj = url.parse(req.url, true)
    
      switch (pathObj.pathname) {
        case '/getNews':
          var news = [
            "第11日前瞻:中国冲击4金 博尔特再战200米羽球",
            "正直播柴飚/洪炜出战 男双力争会师决赛",
            "女排将死磕巴西!郎平安排男陪练模仿对方核心"
            ]
          res.setHeader('Content-Type','text/json; charset=utf-8')
          if(pathObj.query.callback){
            res.end(pathObj.query.callback + '(' + JSON.stringify(news) + ')')
          }else{
            res.end(JSON.stringify(news))
          }
    
          break;
    
        default:
          fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){
            if(e){
              res.writeHead(404, 'not found')
              res.end('<h1>404 Not Found</h1>')
            }else{
              res.end(data)
            }
          }) 
      }
    }).listen(8080)
    
    jsonp测试1.png
    jsonp测试2.png
    • CORS
      index.html
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>news</title>
    <style>
      .container{
        width: 900px;
        margin: 0 auto;
      }
    </style>
    </head>
    <body>
      <div class="container">
        <ul class="news">
          <li>博彩赔率挺中国夺回第二纽约时报:中国因对手服禁药而丢失的奖牌最多</li>
          <li>最“出柜”奥运?同性之爱闪耀里约 </li> 
          <li>跪拜谢与洪荒之力一样 都是真情流露</li>
        </ul>
        <button class="change">换一组</button>
      </div>
      
    <script>
      
      $('.change').addEventListener('click', function(){
        var xhr = new XMLHttpRequest();
        xhr.open('get', 'http://127.0.0.1:8080/getNews', true);
        xhr.send();
        xhr.onreadystatechange = function(){
          if(xhr.readyState === 4 && xhr.status === 200){
            appendHtml( JSON.parse(xhr.responseText) )
          }
        }
        window.xhr = xhr
      })
      function appendHtml(news){
        var html = '';
        for( var i=0; i<news.length; i++){
          html += '<li>' + news[i] + '</li>';
        }
        console.log(html);
        $('.news').innerHTML = html;
      }
      function $(id){
        return document.querySelector(id);
      }
    </script>
    
    </html>
    

    server.js

    var http = require('http')
    var fs = require('fs')
    var path = require('path')
    var url = require('url')
    
    http.createServer(function(req, res){
      var pathObj = url.parse(req.url, true)
    
      switch (pathObj.pathname) {
        case '/getNews':
           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.setHeader('Access-Control-Allow-Origin','http://localhost:8080')
          //res.setHeader('Access-Control-Allow-Origin','*')
          res.end(data);
          break;
        default:
          fs.readFile(path.join(__dirname, pathObj.pathname), function(e, data){
            if(e){
              res.writeHead(404, 'not found')
              res.end('<h1>404 Not Found</h1>')
            }else{
              res.end(data)
            }
          }) 
      }
    }).listen(8080)
    
    cors测试1.png
    cors测试2.png
    • 降域
      a.html
    <html>
    <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>
    
    <div class="ct">
        <h1>使用降域实现跨域</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>
    //URL: http://a.jrg.com:8080/a.html
    document.querySelector('.main input').addEventListener('input', function(){
      console.log(this.value);
      window.frames[0].document.querySelector('input').value = this.value;
    })
    document.domain = "jrg.com"
    </script>
    
    </html>
    

    b.html

    <html>
    <style>
        html,body{
            margin: 0;
        }
        input{
            margin: 20px;
            width: 200px;
        }
    </style>
    
        <input id="input" type="text"  placeholder="http://b.jrg.com:8080/b.html">
    <script>
    // URL: http://b.jrg.com:8080/b.html
     
    document.querySelector('#input').addEventListener('input', function(){
        window.parent.document.querySelector('input').value = this.value;
    })
    document.domain = 'jrg.com';
    </script>
    </html>
    
    降域测试.png
    利用document.domain 实现跨域

    补充说明:Windows10系统如何更改hosts

    1. 管理员身份打开命令行


      步骤1.png

      2.在命令行输入notepad 回车,以管理员身份打开记事本


      步骤2.png
      3.打开的记事本页面中点右上角的文件,然后打开,找到C:\Windows\System32\drivers\etc路径下的hosts文件,点击打开
      步骤3.png

      4.在最下行输入要添加的修改文件,保存关闭


      步骤4.png
    • postMessage
      a.html
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
      <title>降域</title>
      <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>
    

    b.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title>降域</title>
        <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>
    
    postMessage测试.png

    相关文章

      网友评论

          本文标题:进阶13 JSONP 跨域

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