跨域之二:JSONP 和 CORS

2017-02-15  本文已影响0人  NathanYangcn

本节内容:实现跨域常用的两种方式 —— JSONP 和 CORS

零:跨域报错展示

在非同源情况下,调用 Ajax 向服务端请求数据时,浏览器会阻止这一操作,并且报错如下:


跨域报错 —— Ajax

既然出现了相应的问题,便会有对应的解决办法随之而生:可以使用 JsonP 和 CORS 解决跨域问题。

127.0.0.1 localhost
127.0.0.1 a.yang.com
127.0.0.1 b.yang.com
127.0.0.1 yang.com

一、JSONP

因为需要突破同源策略,所以 JSONP 就应运而生了。

两个定义结合来看,个人觉得更好一些。
可以简单来理解,JSONP 就是跨域的一种实现方式,不要让名称混淆视听。

JSONP 全称 JSON with Padding,是数据格式 JSON 的一种 “使用模式”,可用于解决主流浏览器的跨域数据访问的问题。—— 来自百度百科的解释

JSONP 是一种非正式传输协议,该协议的一个要点就是允许用户传递一个 callback 参数给服务端,然后服务端返回数据时会将这个 callback 参数作为函数名来包裹住 JSON 数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。—— 参考文章

[](【备注】——script 标签引用资源得本质是:
1)向 src 发送请求
2)将资源下载到当前页面
3)当资源加载完毕后,把该资源当做 JS 代码来立刻执行——【备注】)

  1. 动态创建 script 标签,src 地址指向数据接口,并传递 callback 参数
  2. 定义数据处理函数
  3. 服务端接收请求,解析参数,计算数,返回回调函数字符串
  4. 将回调函数字符串引入页面并作为 JS 去执行:此时会调用数据处理函数,数据会作为数据处理函数的参数被处理计算出一个结果

自己动手,丰衣足食。我来手动演练一番。

var btn = document.querySelector('.btn'),
        panal = document.querySelector('.panal');

    btn.addEventListener('click', function () {
        var script = document.createElement('script');
        script.src = 'http://b.yang.com:8080/loadData?callback=onSuccess';
        document.head.appendChild(script);
        document.head.removeChild(script);
    });

    function onSuccess(data) {
        panal.innerText = data;
    }

服务端 router 代码

app.get('/loadData', function(req, res) {
        var dataStr = '';
        var len = 10;
        var disc = 'abcdefjhigklmnopqrstuvwxyz';
        for(var i = 0; i < len; i++){
            dataStr += disc[Math.floor(Math.random() * disc.length)];
        }
        var callback = req.query.callback;
        data = callback + '(' + JSON.stringify(dataStr) + ');';
        res.send(data);
});

二、CORS

因为 JSONP 存在缺点,所以在发展过程中,便会有新的技术出现来更好的解决跨域问题,这时出现了 CORS。

CORS 就是一种跨域问题的解决方案:它定义了一种跨域访问的机制,允许网页从不同的域访问其资源。与 JSONP 相比,更为方便可靠。

CORS 全称 Cross-Origin Resource Sharing,即:跨来源资源共享。它是一份浏览器技术的规范,提供了Web服务从不同网域传来沙盒脚本的方法,以避开浏览器的同源策略,是JSONP模式的现代版。——来自必应的解释

  1. 当使用 XMLHttpRequest 发送请求时,如果浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin;
  2. 后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;
  3. 浏览器判断该响应头中是否包含 Origin 的值:
  4. 如果包含浏览器则会处理响应,前端就可以拿到响应数据;
  5. 如果不包含浏览器直接驳回,此时前端无法拿到响应数据。

简单来说,就是浏览器匹配请求头和响应头,如果符合要求便可拿到数据,否则无法拿到数据。整个过程都是由浏览器自动完成。这就像一个白名单,代表着谁可以拿到数据。

自己动手,丰衣足食。我来手动演练一番。

var btn = document.querySelector('.btn'),
        panal = document.querySelector('.panal');

    btn.addEventListener('click', function () {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if(xhr.readyState === 4){
                if(xhr.status === 200){
                    onSuccess(xhr.responseText);
                }
            }
        }
        xhr.open('post', 'http://b.yang.com:8080/loadData', true);
        xhr.send();
    });

    function onSuccess(data) {
        panal.innerText = data;
    }

服务端 router 代码

app.post('/loadData', function(req, res) {
        var disc = 'abcdefjhigklmnopqrstuvwxyz';
        var data = '';
        for(var i = 0; i < 10; i++){
            data += disc[Math.floor(Math.random() * disc.length)];
        }
        res.header("Access-Control-Allow-Origin", "http://a.yang.com:8080");
        res.send(data);
});
最后:jsonp 和 cors 都是主流的跨域方式,最主要的还是看需求,其中最大的问题就是兼容程度,请按需选择。

本文章著作权归饥人谷和本人所有,转载须说明来源!

上一篇 下一篇

猜你喜欢

热点阅读