欧庆春,邯郸生活资讯,内心独白
利用<script>标签没有跨域限制的“漏洞”来达到与第三方通讯的目的。当需要通讯时,本站脚本创建一个<script>元素,地址(src属性)指向第三方的API网址,并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。例如: <script src="https://www.example.net/api?param1=1¶m2=2"></script>
第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),例如:
callback(json数据)这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。
举个简单的例子:
首先用node搭建一个服务器:
'use strict'; //通过require将http库包含到程序中 var http = require('http'); //引入url模块解析url字符串 var url = require('url'); //引入querystring模块处理query字符串 var querystring = require('querystring'); //创建新的HTTP服务器 var server = http.createServer(); //通过request事件来响应request请求 server.on('request',function(req, res){ var urlPath = url.parse(req.url).pathname; var qs = querystring.parse(req.url.split('?')[1]); if(urlPath === '/jsonp' ){ res.writeHead(200,{'Content-Type':'application/json;charset=utf-8'}); var data = { "name": "JSONP" }; data = JSON.stringify(data); var callback = qs.callback+'('+data+');'; res.end(callback); } else{ res.writeHead(200, {'Content-Type':'text/html;charset=utf-8'}); res.end('Hell World\n'); } }); //监听8088端口 server.listen('8088'); //用于提示我们服务器启动成功 console.log('Server running!');
然后,创建一个页面
<script> function test(data){alert(data.name);}; </script> <script src="https://127.0.0.1:8088/jsonp?callback=test"></script>
基本思路:
1. 根据传入的url、参数拼接成完整的url,可以为url提供一个时间戳来避免浏览器缓存
2. 把传入的回调函数作为callback参数补充到传入的URL(真正要访问的跨域的URL)中
3. 动态创建出script元素并触发URL的访问。浏览器获取返回的JS代码并执行,也就是执行了传入的回调函数。
核心代码:
JSONP.prototype = { // 时间戳,避免浏览器缓存 now:function() { return (new Date()).getTime(); }, // 删除节点 removeElem:function(elem) { var parent = elem.parentNode; if(parent && parent.nodeType !== 11) { parent.removeChild(elem); } }, // 拼接url参数 parseParam:function() { var param="",data = this.options; if("string" === typeof data) { param = data; }else if("object" === typeof data) { for(var item in data) { param += "&" + item + "=" + encodeURIComponent(data[item]); } } param += "&_stamp=" + this.now(); return param; }, getJSONP:function() { var id = (this.options.name || '__jp') + (count++); this.url += "?"; this.url += this.parseParam(); this.url = this.url.replace('?&', '?'); if(this.fn) { this.url += "&callback=" + this.fn; } // 创建一个script元素 var script = document.createElement("script"); script.type = "text/javascript"; // 设置要远程的url script.src = this.url; // 设置id,为了后面可以删除这个元素 script.id = id; var _this = this; // 把传进来的函数重新组装,并把它设置为全局函数,远程就是调用这个函数 window[id] = function(json) { // 执行这个函数后,要销毁这个函数 window[id] = undefined; // 获取这个script的元素 var elem = document.getElementById(id); // 删除head里面插入的script,这三步都是为了不影响污染整个DOM啊 _this.removeElem(elem); // 执行传入的的函数 _this.fn(json); }; // 在head里面插入script元素 var head = document.getElementsByTagName("head"); if(head && head[0]) { head[0].appendChild(script); } } };
应用方式:
还是利用刚才的服务器,然后在页面引用并使用:
new JSONP({
url:url,
data:data,
callback:callback
})
url是后端地址,data是参数,即url链接“?”后的内容(可选),callback是回调函数。
<script src="jsonp.js"></script> <script> function test(data){alert(data.name);}; var data = { output: "json" } new JSONP({ url:"https://127.0.0.1:8088/jsonp", data:data, callback:"test" }); </script>
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
怎么理解wx.navigateTo的events参数使用详情
微信jssdk踩坑之签名错误invalid signature
网友评论