JSONP的实现流程

  在进行AJAX的时候会经常产生这样一个报错:

  看红字,这是浏览器的同源策略,使跨域进行的AJAX无效。注意,不是不发送AJAX请求(其实就是HTTP请求),而是请求了,也返回了,但浏览器‘咔擦’一声,下面没有了。对比下fiddler和浏览器抓的包的异同:
  fiddler:

  

  chrome:

  简而言之,浏览器这边就是头(response header)给看,身体(response body)不给看。

  什么是同源策略?为什么会有同源策略?这一点在吴翰清老师著的《白帽子讲Web安全》一书中由阐述,这里就不赘述了。下面要做的,就是使用JSONP让上面的报错消失,按正确的流程进行下去。

  首先介绍下我这里的环境,两个Web服务器,Tomcat监听8081,Node监听3000,Tomcat这边实现一个处理AJAX的JSP文件,很简单,返回一个JSON
  

<%@ page contentType="application/json; charset=utf-8" %>
{"status": true}

  Tomcat的页面对这个URL发出AJAX请求,并打印出了返回值

  但Node的页面发出AJAX请求,则像上面那样报错了,因为AJAX有同源策略保护。怎么绕过这个保护呢?平时我们页面引入的CSS、JS可能是从其他的服务器比如静态服务器、CDN获取内容,都在不同的域,可知页面内的标签引入JS是没有同源策略一说的,而且也是进行request和处理response,于是我们把这个AJAX请求改为如下代码:

var script = document.createElement(‘script‘);
script.src = ‘http://localhost:8081/test/true.jsp‘;
document.body.insertBefore(script, document.body.lastChild);

  但还是残忍的报错了

  因为返回的JSON({"status": true})成为了一个独立的js片段,而这个片段明显是不符合语法的,如果返回的是符合语法规范的处理JSON的js片段而不仅仅是JSON就好了。比如我们将服务器端的代码改成这样:

<%@ page contentType="application/javascript; charset=utf-8" %>
console.log({"status": true});

  再在Node的页面进行AJAX

  目的是达到了,但问题是,这个AJAX的servlet不仅返回了数据,还返回了行为,难道我要把处理DOM的js写在这里面吗?页面重构了又跑到这里来修改?问题太美不敢想,所以请求成功的方法必须写在页面的js里面,比如这样

function callback(data) {
    console.log(data);
}
var script = document.createElement(‘script‘);
script.src = ‘http://localhost:8081/test/true.jsp‘;
document.body.insertBefore(script, document.body.lastChild);

  而服务器返回的js片段直接调用这个function就行了,这个就叫回调函数了

<%@ page contentType="application/javascript; charset=utf-8" %>
callback({"status": true});

  可以看到,这个方案比之前好多了,servlet和请求页面的耦合度低了很多,但没完全解决,比如callback这个回调函数的名字,如果把这个名字放在请求的parameter中,比如这样

function callback(data) {
    console.log(data);
}
var script = document.createElement(‘script‘);
script.src = ‘http://localhost:8081/test/true.jsp?cb=callback‘;
document.body.insertBefore(script, document.body.lastChild);

  服务器对这个parameter进行处理

<%@ page contentType="application/javascript; charset=utf-8" %>
<%= request.getParameter("cb") %>({"status": true});

  优化一下,对没有cb参数的请求仅返回JSON

<%
    String callback = request.getParameter("cb");
    if(null == callback) {
        response.setContentType("application/json; charset=utf-8");
%>
    {"status": true}
<%
    }else {
        response.setContentType("application/javascript; charset=utf-8");
%>
    <%= callback %>({"status": true})
<%
    }
%>

  那么整个JSONP的功能就实现了。但还有一点瑕疵,代码执行完html中留下了一个script标签,强迫症能忍?处女座能忍?

  解决方法:可以使用jQuery的方法,jQuery会清除掉留下的script标签。

$.ajax({
    url: ‘http://localhost:8081/test/true.jsp‘,
    dataType: "jsonp",
    jsonp: "cb",
    success: function (data) {
        console.log(data)
    }
});

  也可以自己实现一个,我抛个砖,在js加载完成后删除节点。

function callback(data) {
    console.log(data);
}
var script = document.createElement(‘script‘);
script.src = ‘http://localhost:8081/test/true.jsp?cb=callback‘;
document.body.insertBefore(script, document.body.lastChild);
script.onload = function(){
    this.parentNode.removeChild(this);
};

  JSONP的东西就到此结束了,其实做完才发现,实际上这是个很简单的概念,取了个比较唬人的名字而已。

时间: 2024-10-12 20:22:58

JSONP的实现流程的相关文章

JSONP原理小记

大家都知道JSONP(JSON with padding参数式JSON)是跨域传输数据的方法,jq等很多类库都封装了JSONP的方法,但是他的原理是怎样的呢?下面举个我认为最浅显的栗子,大家看过了都会明白原理! JSONP的原理,概括点说,就是动态插入<script>元素,当然<script>元素引用的js文件是服务器传过来的,他与<img>元素一样可以不受限制地从其他域加载资源. 栗子: <!DOCTYPE html><html> <he

jsonp的概念

参考链接:https://www.imooc.com/article/18739    https://blog.csdn.net/u011897301/article/details/52679486 https://www.cnblogs.com/wangyuyu/articles/3388169.html 1.什么是jsonp以及jsonp的产生背景? jsonp全称为json with padding. 1.一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静

jQuery源码分析系列(36) : Ajax - 类型转化器

什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的响应只有 responseText与responseXML 二种 所以现在我要定义dataType为jsonp,那么所得的最终数据是一个json的键值对,所以jQuery内部就会默认帮你完成这个转化工作 jQuery为了处理这种执行后数据的转化,就引入了类型转化器,如果没有指定类型就依据响应头Con

JavaScript 九种跨域方式实现原理

前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS.CSFR 等***.所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源.同源策略限制内容有: Cookie.LocalStorage.IndexedDB 等存储性内容DOM 节点AJAX 请求发送

几种常见的跨域原理的实现

一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS.CSFR 等攻击.所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源. 同源策略限制内容有: Cookie.LocalStorage.IndexedDB 等存储性内容 DOM 节点 AJAX 请求发送后,结果被浏览器拦截了 但是有三个标签是允许跨域加载资源: <img src=XXX&g

九种跨域方式实现原理

前言 前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容. 本文完整的源代码请猛戳github 博客 一.什么是跨域? 1.什么是同源策略及其限制内容? 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到 XSS.CSFR 等攻击.所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个 ip 地址,也非同源. 同源策略限制内容有: Cookie.LocalStorage.IndexedDB

jQuery-1.9.1源码分析系列(十六)ajax——ajax处理流程以及核心函数

先来看一看jQuery的ajax核心处理流程($.ajax) a. ajax( [url,] options )执行流程 第一步,为传递的参数做适配.url可以包含在options中 //传递的参数只是一个对象 if ( typeof url === "object" ) { options = url; url = undefined; } //options强制转成对象 options = options || {}; 第二步,创建一些变量,比较重要的是:创建最终选项对象s.全局事

JSONP超简单例子,一看就能上手

JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议.JSONP解决了ajax跨域请求的问题,JSONP只是解决跨域请求方案中的一种. 下面基于Servlet简单介绍一下JSONP接口的开发流程: 1, 创建一个Servlet接口JsonpServlet class  JsonpSe

js实现跨域(jsonp, iframe+window.name, iframe+window.domain, iframe+window.postMessage)

一.浏览器同源策略 首先我们需要了解一下浏览器的同源策略,关于同源策略可以仔细看看知乎上的一个解释.传送门 总之:同协议,domain(或ip),同端口视为同一个域,一个域内的脚本仅仅具有本域内的权限,可以理解为本域脚本只能读写本域内的资源,而无法访问其它域的资源.这种安全限制称为同源策略. ( 现代浏览器在安全性和可用性之间选择了一个平衡点.在遵循同源策略的基础上,选择性地为同源策略"开放了后门". 例如img script style等标签,都允许垮域引用资源.) 下表给出了相对