跨域的常见解决方式

document.domain降域

我们为静态服务器设置了两个域名分别为a.both.comb.both.com,并设置了两个静态网页,分别为a.htmlb.html,在a网页中内嵌了b网页,iframe的src设置为b.both.com,并在a网页中显示b网页中的信息,网页代码如下:

//a.html
<h1>This is a.html page</h1>
<iframe src="http://b.both.com:8080/b.html" frameborder="1"></iframe>
<script>
    var h = document.querySelector('h1');
    var ele = document.createElement('p');
    var iframe = document.querySelector('iframe');
    iframe.onload = function(){
        var str = iframe.contentWindow.data;
        var text = document.createTextNode(str);
        ele.appendChild(text);
        h.after(ele);
    }
</script>
//b.html
<h1>This is b.html page</h1>
<script>
    window.data = 'information in b.html';
</script>

我们通过a.both.com域名,访问a.html网页,实现跨域,此时网页并没有显示从b网页获取data信息,并且报错了

没有设置document.domain
然后,在a.html``b.html网页中都添加document.domain = 'both.com';实现降域,以便跨域访问信息,得到如下效果:
设置document.domain = 'both.com'
获取到了信息没有报错

JSONP

JSONP方法是网页通过添加一个<script>元素,向服务器请求 JSON 数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
我们创建了静态服务器,域名修改为a.comb.com,通过域名a.com访问域名为http://b.com:8080的资源,有如下代码:

//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 '/getInfo':
      var info = ['This','is','information','from','server'];
      res.setHeader('Content-Type','text/json; charset=utf-8')
      if(pathObj.query.callback){
        res.end(pathObj.query.callback + '(' + JSON.stringify(info) + ')')
      }else{
        res.end(JSON.stringify(info))
      }
      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)
//index.html
<h1>CORS</h1>
<script>
    function showData(data){
        for(var i = 0; i < data.length; i++){
            console.log(data[i]);
        }
    }
</script>
<script src="http://b.com:8080/getInfo?callback=showData"></script>
数据访问成功

可以得到我们想要的数据

CORS

CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。

//index.html
<h1>CORS</h1>
<script>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://b.com:8080/getInfo', true);
    xhr.send();
    xhr.onload = function(){
        console.log(JSON.parse(xhr.responseText));
    }
</script>
//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 '/getInfo':
      var info = ['This','is','information','from','server'];
      res.setHeader('Access-Control-Allow-Origin','http://a.com:8080')
      res.setHeader('Content-Type','text/json; charset=utf-8')
      if(pathObj.query.callback){
        res.end(pathObj.query.callback + '(' + JSON.stringify(info) + ')')
      }else{
        res.end(JSON.stringify(info))
      }
      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)

效果图如下:

输出结果,没有报错

请求与响应文件:
请求头和响应头

可以发现响应头的Access-Control-Allow-Origin和请求头的Origin是一致的,所以可以实现跨域访问。

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

推荐阅读更多精彩内容