一、同源战略
同源战略,它是由Netscape提出的一个有名的安全战略,如今一切的可支撑javascript的浏览器都邑运用这个战略。
为何须要同源战略,这里举个例子:
假定如今没有同源战略,会发作什么事变呢?人人晓得,JavaScript能够做很多东西,比方:读取/修正网页中某个值。恩,你如今打开了浏览器,在一 个tab窗口中打开了银行网站,在别的一个tab窗口中打开了一个歹意网站,而谁人歹意网站挂了一个的特地修正银行信息的JavaScript,当你接见 这个歹意网站而且实行它JavaScript时,你的银行页面就会被这个JavaScript修正,效果会异常严峻!而同源战略就为了防备这类事变发作.
比方说,浏览器的两个tab页中离别打开了http://www.baidu.com/index.X19Xhtml和http: //www.google.com/index.html,个中,JavaScript1和JavaScript3是属于百度的剧本,而 JavaScript2是属于谷歌的剧本,当浏览器的tab1要运转一个剧本时,便会举行同源搜检,只要和www.baidu.com同源的剧本才被执 行,所谓同源,就是指域名、协定、端口雷同。所以,tab1只能实行JavaScript1和JavaScript3剧本,而JavaScript2不能 实行,从而防备其他网页对本网页的不法改动。
二、什么是JSONP?
JSONP(JSON with Padding)是一个非官方的协定,它许可在服务器端集成Script tags返回至客户端,经由过程javascript callback的情势完成跨域接见(这仅仅是JSONP简朴的完成情势)。
三、为何运用JSONP?
由于 JSON 只是一种含有简朴括号构造的纯文本,因而很多通道都能够交流 JSON 音讯。由于同源战略的限定,我们不能在与外部服务器举行通讯的时刻运用 XMLHttpRequest。而JSONP是一种能够绕过同源战略的要领,即经由过程运用 JSON 与 < script> 标记相结合的要领,从服务端直接返回可实行的JavaScript函数挪用或许JavaScript对象。
实在 jsonp 是个很简朴的一个东西。主假如应用了 <script/>标签对javascript文档的动态剖析来完成。(实在也能够用eval函数)。
<script type="text/javascript">
function jsonpCallback(result) {
alert(result.msg);
}
</script>
<script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback"></script>
个中 jsonCallback 是客户端注册的,猎取跨域服务器上的json数据后,回调的函数。
http://crossdomain.com/jsonServerResponse?jsonp=jsonpCallback
这个 url 是跨域服务器取 json 数据的接口,参数为回调函数的名字,返回的花样为:
jsonpCallback({ msg:'this is json data'})
Jsonp道理:
首先在客户端注册一个callback, 然后把callback的名字传给服务器。此时,服务器先天生 json 数据。然后以 javascript 语法的体式格局,天生一个function , function 名字就是通报上来的参数 jsonp.
末了将 json 数据直接以入参的体式格局,安排到 function 中,如许就天生了一段 js 语法的文档,返回给客户端。
客户端浏览器,剖析script标签,并实行返回的javascript文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态实行回调函数) .
实在说白了,就是客户端定义一个函数(如a),要求地点后服务器端返回的效果是挪用a函数,须要的数据都放在了a函数的参数内里。
demo:
应为它用到的只是一切 HTML 元素中一个简朴的 script 元素。看到这是否是以为更加奇怪了?没紧要,继承看下去就会厕所(塞)顿开的,嘿嘿~来看个例子吧:
demo.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
</head>
<body>
<script type="text/javascript">
function say(words) {
alert(words);
}
</script>
<script type="text/javascript" src="demo.js"></script>
</body>
</html>
demo.js:
say("Hello, everyone!");
运转 demo.html 文件后,是否是看到写着“Hello, everyone!”的正告框了?你能够会以为这个例子很简朴,没什么了不得的,甚至会在想:这和 JSONP 有关联吗?那末,我能够很一定的通知你:有关联!而且,这个例子实际上就是 JSONP 的原型!你或许会想到,JSONP 不是接见长途数据的吗?对,试想一下,假如 demo.js 文件在别的域的服务器上呢?效果会不会出现问题?我也能够很担任的通知你:不会!你能够将上面例子中的 demo.js 更改成:http://demo.hpyer.cn/php/jsonp.php?callback=say 再试一下。
如今,智慧的你应当已邃晓 JSONP 究竟是怎么回事了,那末,再来解释一下本节开首第一句话吧。看过 demo.js 文件的内容,应当晓得,其只是对一个函数(一般称之为:回调函数)的挪用,而须要交互的数据则经由过程参数情势举行返回。所以经由过程 JSONP 接见的服务器须要供应一个能够设置回调函数名的接口,就像 http://demo.hpyer.cn/php/jsonp.php?callback=say 中的 callback,所以,综上所述 JSONP 是须要服务器端的支撑的。附上 jsonp.php 的源码:
<?php
$type = isset($_GET['type']) ? $_GET['type'] : '';
$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
$json = '';
if ($type == 'json') {
$json = '{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": "100"
},
"IDs": [116, 943, 234, 38793]
}
}';
} else {
$json = '"Hello, everyone!"';
}
if (!empty($callback)) {
$json = $callback . '(' . $json . ')';
}
echo $json;
jquery 中的运用:
自 1.2 版本起,jQuery 加入了对 JSONP 的支撑。我们能够很轻易的应用 $.getJSON() 要领(或许别的基于 $.ajax() 的要领),来跨域加载 JSON 数据。来个例子吧:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Demo</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
function do_jsonp() {
$.getJSON("http://demo.hpyer.cn/php/jsonp.php?type=json&callback=?",
function(data) {
$('#result').val('data.Image.IDs: ' + data.Image.IDs);
});
}
</script>
</head>
<body>
<a href="javascript:do_jsonp();">Click me</a><br />
<textarea id="result" cols="50" rows="5"></textarea>
</body>
</html>
你能够注重到上面的例子中,url 被写成了 http://demo.hpyer.cn/php/jsonp.php?type=json&callback=?,须要申明的是,这个问号会被 jQuery 自动替换为回调函数的函数名(假如是一个匿名函数,jQuery 会自动天生一个带时候戳的函数名)。
看我在项目中的一个例子:
//定义Ajax函数
function ajaxFun() {
var timeStamp = Math.floor(new Date().getTime() / 1000);
var url = "http://apiso.alidemo.3gpp.cn/httpserver/cp/yisou/ali_feedback_interface.php?callback=jsonpCallback&feedbacktype=add&type=" + feedbackNumber + "&book=" + me.mixedInfo.title + "&author=" + me.mixedInfo.author + "&chapter=" + me.mixedInfo.cname + "&chapterid=" + me.mixedInfo.cid + "&questiondesc=" + text + "&platform=1&t=" + timeStamp + "&sn=" + md5("d30fcd1a9f1900fa049b4766e0a275e1" + timeStamp);
var scriptObj = document.createElement("script");
scriptObj.src = url;
scriptObj.id = "jsonpScript";
document.body.appendChild(scriptObj);
//jsonp回调函数,jsonpCallback必需为全局函数,由于jsonp返回的是在全局环境中实行函数的语句,即jsonpCallback(data)
window.jsonpCallback = function(data) {
switch (data.code) {
case "1":
novel.readerPrompt('提交胜利,行将返回……', 1, function() {
window.history.go(-1);
});
break;
case "0":
novel.readerPrompt('提交失利。', 2);
break;
case "900":
novel.readerPrompt('提交失利,考证失利。', 2);
break;
}
//胜利后删除scriptObj,背面的setTimeout就不会实行了
if (document.getElementById("jsonpScript")) {
document.body.removeChild(scriptObj);
}
}
//设置超时,超时的话直接显现提交胜利
setTimeout(function() {
if (document.getElementById("jsonpScript")) {
document.body.removeChild(scriptObj);
novel.readerPrompt('提交胜利,行将返回……', 1, function() {
window.history.go(-1);
});
}
}, 2000);
}
ajaxFun();
via WEB前端开辟