说一说javascript跨域和jsonp
同源策略
在浏览器的安全策略中“同源策略”非常如雷贯耳,说的是协议、域名、端口相同则视为同源,域名也可换成IP地址,不同源的页面脚本不能获取对方的数据。
要是想使用XMLHttpRequest或者常规的AJAX请求获取另一个站点的数据,浏览器会告诉你“XXXX is not allowed by Access-Control-Allow-Orign”.
因为同源策略的存在,防止了跨域访问的安全问题,但同时也损失了方便获取资源的便利。
跨域的src属性
世事又非绝对,浏览器还是允许几个元素跨域访问外部资源的,如:<script>,<img>,<iframe>,也就是说,在html元素中拥有src属性的元素是可以跨域访问资源。
通过src属性,img可以引用其它站点或图床的图片,大大降低本站的图片持久。
通过src属性,script可以引用CDN的JS文件,加速了浏览器的脚本文件的下载,跨域的数据获取更加高效和方便。
通过src属性,iframe可以嵌入其它站点的页面,可以让页面的框架和可变内容分离,内容引用较为灵活,方便引用其它站点,虽然现在越来越不建议使用它。
正因为跨域访问的存在,web世界才能更加的精彩。
而JSONP正式利用了script标签的跨域能力。
JSONP
全名JSON with padding
就是通过约定,访问跨域服务器上数据的方法。
这种约定其实就是一个函数定义,并且具备数据参数的定义,由跨域服务器的脚本或动态生成的脚本调用并且传递数据参数。
该函数称之为“跨域回调函数”。
1.一个简单的跨域脚本调用
本地服务器上的一个脚本,直接引用了跨域服务器上的脚本文件。
<html> <head><title>test</title> </head> <body><scriptsrc="http://localhost:3001/javascripts/jsonpsrc1.js"></script> </body> </html>
跨域服务器上的脚本jsonpsrc1.js
alert('hi 我们不是一个域的哦');
运行后,浏览器访问本地服务器上的页面,会弹出alert
2.跨域传递数据
在本地服务器的脚本中,约定一个函数,名为jsonpCallback跨域回调函数交由跨域服务器上的脚本调用。
注意,jsonpCallback跨域回调函数的定义必须是在引用跨域服务器上的脚本之前。
<html> <head><title>test</title> </head> <body> <script>functionjsonpCallback(data){alert(JSON.stringify(data,null,2));}</script> <scriptsrc="http://localhost:3001/javascripts/jsonpsrc2.js"></script> </body> </html>
跨域服务器上的脚本jsonpsrc2.js,按照约定的跨域回调函数名调用,并传递一个数据对象。
jsonpCallback({name:'白色的海',age:90
});
运行后,浏览器访问本地服务器上的页面,会弹出alert,显示跨域服务器传递过来的数据。
3.动态跨域回调函数
通过上面的2种方法已经基本实现了JSONP的使用,但是还存在一个问题,就是必须要提前约定这个跨域回调函数的名字 。
每次都要按照跨域服务器上的的回调函数名进行定义,极为不便。
那么两个跨域的脚本引用能否不绑定同一个函数名称呢。
可以在本地服务器脚本中任意定义跨域回调函数的名称,将该函数名用过参数请求给跨域服务器,在跨域服务器后台代码上动态拼接生成回调函数的调用字符串并响应给请求方。
在这里是用node.js+express的运行环境,并且以一个简单的查询航班信息的跨域请求进行简单的实现。
在本地服务器页面脚本中定义了showFlightInfo跨域回调函数,用于显示跨域服务器返回的航班信息。
在其后的script标签中对跨域服务器进行了一个JS的请求,并将航班信息和跨域回调函数名带过去。
<html> <head><title>test</title><linkrel="stylesheet"href="/stylesheets/style.css"> </head> <body><h1>航班信息</h1><h1>某航</h1><script>functionshowFlightInfo(data){varflightNoEle=document.createElement('h4');flightNoEle.innerHTML=data.flightNo;varfromEle=document.createElement('h4');fromEle.innerHTML=data.from;vartoEle=document.createElement('h4');toEle.innerHTML=data.to;document.body.appendChild(flightNoEle);document.body.appendChild(fromEle);document.body.appendChild(toEle);}</script><scriptsrc="http://localhost:3001/info/flight?flightNo=MU531&callbackFunc=showFlightInfo"></script> </body> </html>
跨域服务器的后台代码中响应JS请求,接收航班号,生成航班信息,连同跨域回调函数名称拼接成JS字符串后响应请求方。
router.get('/info/flight', function(req, res) {//生成航班信息,这里直接拿请求过来的航班号写一个航班信息对象var data ={flightNo: req.query.flightNo,from:'北京',to:'上海'};//获取请求过来的跨域回调函数名称var callbackFunc =req.query.callbackFunc;//拼成一个JS字符串var s = callbackFunc + '(' + JSON.stringify(data, null, 2) + ');';console.log(s);//通过设置http的header,告知请求方响应的内容是JS脚本res.setHeader('content-type', 'text/javascirpt;charset=utf-8');//res.setHeader('content-language', 'zh-CN') res.write(s);res.end();});
运行后,浏览器访问本地服务器上的页面,会显示跨域服务器上传递过来的航班信息。
为了看得清,将跨域服务器收到的请求和响应的内容输出到控制台,方便查看。
第一行是收到的请求,后面的是对请求的响应,可以看到跨域服务端返回给请求方一个JS的脚本,其中的回调函数名称是请求方定制的。
如此完成JSONP的基本实现。
不只是JSONP
通过跨域请求获取数据本质上是利用了<script>标签的src属性,通过浏览器将跨域的脚本拉过来并同时执行。
那么既然是拉过来执行,那和本页面中的其它脚本的执行没多大区分,那就当然也可以通过生成html元素和css的方式改变页面的显示内容,以实现更丰富的功能,比如广告。
基于上面的航班信息,我要在其中显示一块广告内容,内容来自于跨域服务器。
通过<script>标签引用跨域服务器上对应的广告资源地址
<html> <head><title>test</title><linkrel="stylesheet"href="/stylesheets/style.css"> </head><body><h1>航班信息</h1><scriptsrc="http://localhost:3001/ad"></script><h1>某航</h1><script>functionshowFlightInfo(data){varflightNoEle=document.createElement('h4');flightNoEle.innerHTML=data.flightNo;varfromEle=document.createElement('h4');fromEle.innerHTML=data.from;vartoEle=document.createElement('h4');toEle.innerHTML=data.to;document.body.appendChild(flightNoEle);document.body.appendChild(fromEle);document.body.appendChild(toEle);}</script><scriptsrc="http://localhost:3001/info/flight?flightNo=MU531&callbackFunc=showFlightInfo"></script></body> </html>
跨域服务器的后台代码中响应JS请求,生成一串使用document.write向页面中生成html元素的字符串。
router.get('/ad', function(req, res) {//拼接一JS字符串,完成向html页面中输出html标记var s = 'document.write(\'<div style="background-color:red;width:10rem;height:10rem">我是旅行社广告</div>\');';console.log(s);res.setHeader('content-type', 'text/javascirpt;charset=utf-8');res.write(s);res.end(); });
运行后,浏览器访问本地服务器上的页面,会在航班信息下方显示红色广告位,而这个广告位完全是跨域服务器生成的并且包括样式。
在此基础上,可以做出很多效果,包括将页面某一部分的生成交给专门的或者对应的业务服务器上完成。
转载于:https://www.cnblogs.com/kongxianghai/p/5350079.html
说一说javascript跨域和jsonp相关推荐
- jQuery(三) javascript跨域问题(JSONP解决)
加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...
- JavaScript跨域问题分析与总结_直来直往_百度空间
JavaScript跨域问题分析与总结_直来直往_百度空间 JavaScript跨域问题分析与总结 2009-11-15 16:44 一.为什么需要JS跨域 假设我们构建了一个网上商城www.xxx. ...
- Javascript跨域问题总结
疯狂的JSONP 关于JSON与JSONP简单总结 window.name实现的跨域数据传输 JavaScript跨域总结与解决办法 flash跨域策略文件crossdomain.xml配置详解 转载 ...
- 杨老师课堂之Jquery的筛选,事件,效果,Ajax,javascript跨域)
1 筛选[掌握] 筛选与之前"选择器"雷同,筛选提供函数 1.1 过滤 eq(index|-index),获取第N个元素 •index:一个整数,指示元素基于0的位置,这个元素 ...
- ajax跨域请求Jsonp实现,使用jsonp实现ajax跨域请求
Jsonp(JSON with Padding)是资料格式 json 的一种"使用模式",可以让网页从别的网域获取资料. 由于同源策略,一般来说位于 server1.example ...
- Ajax跨域和JSONP
跨域与JSONP 了解同源策略和跨域 同源策略 1.什么是同源 如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源 判断下表给出的URL地址与http://www.test.com/inde ...
- 【Ajax】Ajax全面讲解、跨域与JSONP及了解HTTP
Ajax 一.初识Ajax 1.1 URL地址 1.1.1 URL地址组成部分 1.2 客户端与服务器的通信过程 1.3 网页中如何请求数据 1.4 资源的请求方式 1.5 Ajax的概念 1.6 j ...
- JavaScript跨域总结与解决办法
JavaScript跨域总结与解决办法 什么是跨域 1.document.domain+iframe的设置 2.动态创建script 3.利用iframe和location.hash 4.window ...
- 服务器端可控情形的Javascript跨域访问解决方法
在最近的一个web项目中为了实现bookmark功能碰到了javascript跨域访问的问题.起初,在google上搜的很多解决方案并不适用于我的情形,只在有一篇文章中提到的远程加载javascrip ...
- WebSocket 解决javascript跨域问题一剂良药
WebSocket 解决javascript跨域问题一剂良药 参考文章: (1)WebSocket 解决javascript跨域问题一剂良药 (2)https://www.cnblogs.com/he ...
最新文章
- 2019年2月26日 Unique Email Addresses、To Lower Case、Encode and Decode TinyURL
- 5、JavaScript进阶篇②——函数、事件、内置对象
- 分布式系统设计的概念
- Mybaitis 缓存的优化
- 帝国Cms百度小程序自然搜索之资源删除功能的使用
- 使用CoreOS及Docker搭建简单的SaaS云平台
- 反射_Class对象功能_获取Field
- 获取当前鼠标的位置以及组件的位置
- C++:05---class和struct
- 程序员面试金典 - 面试题 08.13. 堆箱子(DP)
- Python搭建QQ机器人,监控QQ发言与进群退群,自动@新成员并屏蔽脏话踢人
- ES6,ES5,ES3,对比学习~
- 通信(一) 串口通信
- 玩转软路由 篇一:巨详细的修改Esxi7.0管理端口教程
- 本地服务(local Service)的实现
- 计算机网络显示空白,Win10以太网属性网络选项中显示为空白解决方法
- 笔记3 小程序开发框架
- Referenced file contains errors (http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd)
- 番茄工作法总结-第六章:应变
- xp如何添加桌面计算机回收站,xp系统桌面回收站不见了怎么办
热门文章
- Virtual Earth 添加纽约3D地图
- MySQL Merge存储引擎
- 使用electron-builder对Electron项目进行打包
- SqlServer复制表结构:从另一张表中获取某些字段和类型并添加到一张已经存在的表中...
- jenkins JDK的集成
- 短信转移到另一个手机接收_如何将iPhone手机接收短信同步到另外一台设备上?...
- python设置字符_Python基础教程 将字符串格式设置功能用于字典
- Python如何使用生成器得到斐波那契数列
- liunx上mysql源码安装mysql_搞定linux上MySQL编程(一):linux上源码安装MySQL
- python柱形图绘制_Python Excel 绘制柱形图