跨域之二:JSONP 和 CORS

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

零:跨域报错展示

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


跨域报错 —— Ajax

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

  • 本节会做演练,所以首先修改 hosts 文件,本节演练 hosts 文件增添内容为:
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 就是跨域的一种实现方式,不要让名称混淆视听。

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

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

  • JSONP 的原理
  • 利用 script 标签不受同源策略影响,可以跨域引入外部资源的特性,让服务器端返回可执行的 JS 函数,将要返回的数据作为参数传进函数,以此实现跨域加载数据的目的
  • 此时,绕过 Ajax,并未使用它,但同样达成了请求数据的目的

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

  • JSONP 的使用
  1. 动态创建 script 标签,src 地址指向数据接口,并传递 callback 参数
  2. 定义数据处理函数
  3. 服务端接收请求,解析参数,计算数,返回回调函数字符串
  4. 将回调函数字符串引入页面并作为 JS 去执行:此时会调用数据处理函数,数据会作为数据处理函数的参数被处理计算出一个结果
  • JSONP 的优缺点
  • 优点
    1)因 script 隶属于 HTML 的标签,所以不存在兼容问题

  • 缺点
    1)因需使用 URL 引入资源,所以 JSONP 仅支持 get 请求
    2)因 script 标签会将资源作为 JS 代码执行,所以可能会被注入恶意代码

  • JSONP 演练

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

  • 演练说明
    1)实现的功能:非同源情况下,点击按钮,请求数据,并将数据展示在页面上
    2)当前页面域:a.yang.com ;script 的 src 属性:b.yang.com;
    3)请求的数据:长度为10的随机字符串,选值范围为26个小写英文字母
  • 搭建 web 服务器工具:server-mock
    前端 index 代码
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);
});
  • 尝试改变当前页面的域,与 AJAX 请求域相同或不同,体会一下浏览器的跨域请求、报错提示、同源策略、实现跨域请求。

二、CORS

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

  • 何为 CORS?

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

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

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

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

  • CORS 的使用
  • 前端:正常使用 AJAX 发送请求

  • 服务端:若确定接受请求,则在返回结果中加入响应头:Access-Control-Allow-Origin

  • CORS 的优缺点
  • 优点
    1)使用简单方便、更为安全
    2)支持 POST 请求方式

  • 缺点
    1)CORS 是一种新型跨域问题的解决方案:存在兼容问题——仅支持 IE10 以上

  • CORS 的演练

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

  • 演练说明
    1)实现的功能:非同源情况下,点击按钮,请求数据,并将数据展示在页面上
    2)当前页面域:a.yang.com ;Ajax 请求域:b.yang.com;
    3)请求的数据:长度为10的随机字符串,选值范围为26个小写英文字母
    4)请求方式:post
  • 搭建 web 服务器工具:server-mock
    前端 index 代码
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);
});
  • 尝试改变当前页面的域,与 AJAX 请求域相同或不同,体会一下浏览器的跨域请求、报错提示、同源策略、实现跨域请求。
最后:jsonp 和 cors 都是主流的跨域方式,最主要的还是看需求,其中最大的问题就是兼容程度,请按需选择。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • Section1、为什么要跨域? 自古以来(1995年起),为了用户的信息安全,浏览器就引入了同源策略。那么同源策...
    qhaobaba阅读 366评论 0 0
  • Section1、为什么要跨域? 自古以来(1995年起),为了用户的信息安全,浏览器就引入了同源策略。那么同源策...
    不去解释阅读 476评论 0 0
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    w_zhuan阅读 485评论 0 0
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    他在发呆阅读 812评论 0 0
  • 芬奇狗狗阅读 163评论 0 0