进阶13 JSONP 跨域

题目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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.什么是同源策略浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不...
    24_Magic阅读 506评论 0 0
  • 题目1: 什么是同源策略由于浏览器的安全设置,在利用AJAX进行通信时,默认情况下,XHR对象只能访问与包含它的页...
    饥人谷_桶饭阅读 243评论 0 0
  • 1、 什么是同源策略 同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也是最基本的安全...
    饥人谷_小敏阅读 464评论 0 0
  • 题目1: 什么是同源策略 浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情...
    mhy_web阅读 210评论 0 0
  • 题目1.什么是同源策略? 同源策略(Same origin Policy): 浏览器出于安全方面的考虑,只允许与本...
    FLYSASA阅读 1,746评论 0 6