简单的整理了jsonp跨域的发展
1.何为跨域?
妹纸我问了度娘 跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的。
妹纸觉得度娘说的对,但是也整理了自己对跨域的理解,跨域实际是浏览器的安全机制也就是同源策略作用下产生的,和服务器没有关系,
但是解决跨域问题必须是服务器允许才可以的,浏览器是不能控制跨域的
2.什么是同源策略?
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,
如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
妹纸我盗了以个小哥哥的图看一下同源的意思
3.如何解决跨域问题呢?
很多种方法 比如
document.domain+iframe ,window.name+iframe, 图片ping或script标签跨域 ,还有jsonp
妹纸我呢,就讲讲jsonp跨域的演化过程和原理吧
a. 首先 js的 script标签的src属性 是可以 请求跨域的文件内容, 将来会将内容, 当成js执行
html里面 <script src="http://www.xxx.com/jsonp.php"></script>
php 里面 <?php echo "alert('我是这里的数据’)"; ?>
b. 在使用数据之前必须先引入数据,那么我们的需求是点击按钮才需要加载数据怎么办呢?当然是需要我们自己动态创建script标签啦, 想啥呢哈哈
<?php echo "var a = '我是你要的数据';"; ?>
<button>获取数据</button> <script> var button = document.querySelector("button"); button.onclick = function() { // 动态创建script标签, 动态创建script标签加载内容是需要时间的 var script = document.createElement("script"); script.src = "http://www.xxx.com/jsonp.php"; document.body.appendChild( script );
console.log( a );//这个a是php里面定义的数据变量
c. 但是当我们需要遇到数据请求的很慢的时候,js主线程已经走完了,数据还没过来 那么 这个数据在控制台打印是没定义的会报错
// 定义了一个全局函数 function func( data ) { console.log( data ); } button.onclick = function() { // 动态创建script标签, 动态创建script标签加载内容是需要时间的 var script = document.createElement("script"); script.src = "http://www.xxx.com/jsonp.php"; document.body.appendChild( script ); // 请求结束, 得到结果 'php数据'; script 会将结果当成 js 执行 }
<?php echo "fn('php数据')"; ?>
但是呢。这个函数是死的,每次都需要定死,后台小哥哥可是很不高兴的,怎么办,
那就传一个函数过去,让后台获取,再返还回来,一般传过去的名字都会叫做callback
// 定义了一个全局函数 function fn( data ) { console.log( data ); } button.onclick = function() { // 动态创建script标签, 动态创建script标签加载内容是需要时间的 var script = document.createElement("script"); // 业内规范: 传递函数名时, 键必须叫 callback script.src = "http://www.xxx.com/jsonp.php?callback=fn"; document.body.appendChild( script ); }
<?php header('content-type:text/html;charset=utf-8'); // 接收到前端传递过来的函数名 $callback = $_GET['callback']; // fn echo "$callback('复杂数据')"; // fndata('复杂数据') ?>
总结一下原理吧
初步演化:
1. 利用 script 标签 src 可以跨域的特性, 实现跨域请求数据
2. 就可以动态创建 script 标签, 利用src 请求 服务器端 js 内容的字符串回来
3. 将来在浏览器就可以解析执行 js 内容
后来jsonp:
前端:
1. 定义一个全局函数, 接收后台传递的数据
2. 在通过 script src 请求后台的同时, 拼接上 callback=函数名
后台:
1. 获取到通过 callback 传递过来的函数名
2. 返回函数调用(字符串), 在函数调用中, 以实参的方式将数据返回
最后妹纸我来说说jquery中的jsonp吧
$('button').click(function() { // jsonp 和 ajax 没有关系的 // jquery 将 jsonp 封装到 ajax 方法中, $.ajax({ type: "post", url: "http://www.xxx.com/jsonp.php", // 指定 dataType 为 jsonp, 告诉 jquery, 我们要发送 jsonp 跨域请求 dataType: "jsonp", // jsonp: "callback", success: function( data) { console.log( data); } }) })
原理实际一样,当你把后台数据sleep(10)睡10秒钟的时候,你会发现 jquery让浏览器做了一件事