为了账号安全,请及时绑定邮箱和手机立即绑定

JS里AJAX的使用--(同源策略,如何规避同源策略的jsonp)

标签:
Html5 JavaScript

同源策略:

什么是同源:只有在两个页面的协议(http://或者https://)、域名(www.baidu.com)、端口号(80端口,默认是80)都相同的情况下,这两个页面才是同源的。

同源策略限制的能力:非同源的两个页面,不能互相访问对方设置的本机存储数据、不能互相操作对方的DOM、ajax不能互相发送请求。

什么是跨域:在一台服务器的页面中,请求另一台服务器的数据。这种行为就是跨域(两个非同源服务器互相请求数据)。

AJAX规避同源策略(JSONP):

jsonp的本质:

1、利用标签的src属性可以加载任意服务器的接口内容的特性,把要请求的跨域服务器接口设置在该src属性中,并凭借一个回调函数作为参数;

2、在服务器端收到请求后,取出传进来的函数名,拼接成函数执行的形式,把前端需要的数据设置在函数参数中,一块返还给前端;

3、前端在收到了服务器返回的函数执行码时,开始触发回调函数,在回调函数中就可以获取到想要的数据了;

代码如下:

// 1、创建script标签

var scriptTag = document.createElement('script');

// 2、设置标签类型

scriptTag.type = 'text/javascript';

// 3、设置请求的接口

scriptTag.src = 'http://10.0.153.197:8888/news?callback=getData';

// 4、拼接标签进文档流

window.onload = function() {

document.head.appendChild(scriptTag);

}

// 设置回调函数

function getData (data) {

console.log(data);

}


JSONP的客户端具体实现:


1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。

远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

alert('我是远程文件');

本地服务器localserver.com下有个jsonp.html页面代码如下:

<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://remoteserver.com/remote.js">

毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。



2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

remote.js文件代码如下:

localHandler({"result":"我是远程js带来的数据"});

jsonp.html页面代码如下:

varlocalHandler=function(data){

alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:'+data.result);

};

<script type="text/javascript" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://remoteserver.com/remote.js">

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。





3、其实只要服务端提供的js脚本是动态生成的就行了,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。

看jsonp.html页面的代码:

//得到航班信息查询结果后的回调函数varflightHandler=function(data){

alert('你查询的航班结果是:票价'+data.price+'元,'+'余票'+data.tickets+'张。');

};

//提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)

var url="http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";

//创建script标签,设置其属性

var script=document.createElement('script');

script.setAttribute('src', url);

//把script标签加入head,此时调用开始

document.getElementsByTagName('head')[0].appendChild(script);

这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。

我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。

OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

flightHandler({

"code": "CA1998",

"price": 1780,

"tickets": 5

});

我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!


作者:天上的牛_No1
链接:https://www.jianshu.com/p/0c5d7b1b3931


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消