跨域

作者: Tuuu | 来源:发表于2018-01-07 21:15 被阅读0次

    什么是同源策略

    同源策略(same origin policy),1995年同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策浏览器出于安全方面的考虑,只允许与本域下的接口进行交互。不同源的客户脚本在没有明确授权的情况下,不能读取对方的资源。
    同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据

    本域指的是

    • 同协议:比如都是 http 或者 https
    • 同端口:比如都是 80 端口
    • 同域名:比如都是 google.com

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

    跨域是指通过一定方式绕过浏览器同源政策的限制,可以与不同域进行交互
    目前学习到四种实现形式:

    • JSONP
    • CORS
    • 降域
    • postMessage

    JSONP 的原理是什么

    jsonp 是一种跨域通信的手段,它的原理其实很简单:

    1. 首先是利用 script 标签的 src 属性来实现跨域。
    2. 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。
    3. 由于使用 script 标签的 src 属性,因此只支持 get 方法

    CORS是什么

    • CORS 是一个 W3C 标准,全称是“跨域资源共享”(Cross-origin resource sharing,它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制

    • CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于 IE10。

    • 整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

    因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。

    参考阮一峰

    根据视频里的讲解演示三种以上跨域的解决方式 ,写成博客

    • JSONP
    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)
    
    <!DOCTYPE html>
    <html>
    <body>
      <div class="container">
        <ul class="news">
        </ul>
        <button class="show">show news</button>
      </div>
    
    <script>
       // 通过script标签发送请求
      $('.show').addEventListener('click', function(){
        var script = document.createElement('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>
    
    • CORS
    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('Access-Control-Allow-Origin','*') // 设置响应头中的属性,允许所有的站点访问
          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)
    
    <!DOCTYPE html>
    <html>
    <body>
      <div class="container">
        <ul class="news">
        </ul>
        <button class="show">show news</button>
      </div>
    
    <script>
    
      $('.show').addEventListener('click', function(){
        xhr = new XMLHttpRequest();  // 创建 AJAX 请求
        xhr.open('GET','http://127.0.0.1:8080/getNews',true);
        xhr.send();
        xhr.onload = function(){
          appendHtml(JSON.parse(xhr.responseText));
        }
      })
    
      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>
    
    • postMessage
      postMessage 是 HTML5 新增加的一项功能,跨文档消息传输(Cross Document Messaging),目前:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 都支持这项功能,使用起来也特别简单
      • 首先创建 a.html

        <!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>postMessage</title>
        </head>
        <body>
          <iframe src="http://localhost:8080/b.html" ></iframe>
          <script>
            window.onload = function(){
              var targetOrigin = "http://localhost:8080";
              window.frames[0].postMessage('看到我发给你的信息没', targetOrigin);
            }
            window.addEventListener('message',function(e){
              console.log('a.html接收到信息:',e.data);
            });
          </script>
        </body>
        </html>
        
      • 创建 b.html

        <!DOCTYPE html>
        <html>
        <head>
          <meta charset="UTF-8">
          <title>postMessageB</title>
        </head>
        <body>
          
          <script>
            window.addEventListener('message',function(e){
              if(e.source != window.parent){
                return
              }
              var data = e.data;
              console.log("b.html接收到的消息", data);
              parent.postMessage("我看到你发的消息了", e.origin)
            })
          </script>
        </body>
        </html>
        

    在浏览器中打开 http://localhos/a.html

    postMessage.png

    跨域成功
    参考:MDN

    相关文章

      网友评论

          本文标题:跨域

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