同源策略

在浏览器的安全策略中“同源策略”非常如雷贯耳,说的是协议、域名、端口相同则视为同源,域名也可换成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.一个简单的跨域脚本调用

本地服务器上的一个脚本,直接引用了跨域服务器上的脚本文件。

  1. <html>
  2. <head>
  3. <title>test</title>
  4. </head>
  5. <body>
  6. <script src="http://localhost:3001/javascripts/jsonpsrc1.js"></script>
  7. </body>
  8. </html>

跨域服务器上的脚本jsonpsrc1.js

  1. alert('hi 我们不是一个域的哦');

运行后,浏览器访问本地服务器上的页面,会弹出alert

2.跨域传递数据

在本地服务器的脚本中,约定一个函数,名为jsonpCallback跨域回调函数交由跨域服务器上的脚本调用。

注意,jsonpCallback跨域回调函数的定义必须是在引用跨域服务器上的脚本之前。

  1. <html>
  2. <head>
  3. <title>test</title>
  4. </head>
  5. <body>
  6. <script>
  7. function jsonpCallback(data){
  8. alert(JSON.stringify(data,null,2));
  9. }
  10. </script>
  11. <script src="http://localhost:3001/javascripts/jsonpsrc2.js"></script>
  12. </body>
  13. </html>

跨域服务器上的脚本jsonpsrc2.js,按照约定的跨域回调函数名调用,并传递一个数据对象。

  1. jsonpCallback({
  2. name:'白色的海',
  3. age:90
  4. });

运行后,浏览器访问本地服务器上的页面,会弹出alert,显示跨域服务器传递过来的数据。

3.动态跨域回调函数

通过上面的2种方法已经基本实现了JSONP的使用,但是还存在一个问题,就是必须要提前约定这个跨域回调函数的名字 。

每次都要按照跨域服务器上的的回调函数名进行定义,极为不便。

那么两个跨域的脚本引用能否不绑定同一个函数名称呢。

可以在本地服务器脚本中任意定义跨域回调函数的名称,将该函数名用过参数请求给跨域服务器,在跨域服务器后台代码上动态拼接生成回调函数的调用字符串并响应给请求方。

在这里是用node.js+express的运行环境,并且以一个简单的查询航班信息的跨域请求进行简单的实现。

在本地服务器页面脚本中定义了showFlightInfo跨域回调函数,用于显示跨域服务器返回的航班信息。

在其后的script标签中对跨域服务器进行了一个JS的请求,并将航班信息和跨域回调函数名带过去。

  1. <html>
  2. <head>
  3. <title>test</title>
  4. <link rel="stylesheet" href="/stylesheets/style.css">
  5. </head>
  6. <body>
  7. <h1>航班信息</h1>
  8. <h1>某航</h1>
  9. <script>
  10. function showFlightInfo(data){
  11. var flightNoEle = document.createElement('h4');
  12. flightNoEle.innerHTML=data.flightNo;
  13.  
  14. var fromEle = document.createElement('h4');
  15. fromEle.innerHTML=data.from;
  16.  
  17. var toEle = document.createElement('h4');
  18. toEle.innerHTML=data.to;
  19.  
  20. document.body.appendChild(flightNoEle);
  21. document.body.appendChild(fromEle);
  22. document.body.appendChild(toEle);
  23. }
  24. </script>
  25. <script src="http://localhost:3001/info/flight?flightNo=MU531&callbackFunc=showFlightInfo"></script>
  26. </body>
  27. </html>

跨域服务器的后台代码中响应JS请求,接收航班号,生成航班信息,连同跨域回调函数名称拼接成JS字符串后响应请求方。

  1. router.get('/info/flight', function (req, res) {
  2. //生成航班信息,这里直接拿请求过来的航班号写一个航班信息对象
  3. var data = {
  4. flightNo: req.query.flightNo,
  5. from: '北京',
  6. to: '上海'};
  7.  
  8. //获取请求过来的跨域回调函数名称
  9. var callbackFunc = req.query.callbackFunc;
  10.  
  11. //拼成一个JS字符串
  12. var s = callbackFunc + '(' + JSON.stringify(data, null, 2) + ');';
  13. console.log(s);
  14.  
  15. //通过设置http的header,告知请求方响应的内容是JS脚本
  16. res.setHeader('content-type', 'text/javascirpt;charset=utf-8');
  17. //res.setHeader('content-language', 'zh-CN')
  18. res.write(s);
  19. res.end();
  20.  
  21. });

运行后,浏览器访问本地服务器上的页面,会显示跨域服务器上传递过来的航班信息。

为了看得清,将跨域服务器收到的请求和响应的内容输出到控制台,方便查看。

第一行是收到的请求,后面的是对请求的响应,可以看到跨域服务端返回给请求方一个JS的脚本,其中的回调函数名称是请求方定制的。

如此完成JSONP的基本实现。

不只是JSONP

通过跨域请求获取数据本质上是利用了<script>标签的src属性,通过浏览器将跨域的脚本拉过来并同时执行。

那么既然是拉过来执行,那和本页面中的其它脚本的执行没多大区分,那就当然也可以通过生成html元素和css的方式改变页面的显示内容,以实现更丰富的功能,比如广告。

基于上面的航班信息,我要在其中显示一块广告内容,内容来自于跨域服务器。

通过<script>标签引用跨域服务器上对应的广告资源地址

  1. <html>
  2. <head>
  3. <title>test</title>
  4. <link rel="stylesheet" href="/stylesheets/style.css">
  5. </head>
  6. <body>
  7. <h1>航班信息</h1>
  8. <script src="http://localhost:3001/ad"></script>
  9. <h1>某航</h1>
  10. <script>
  11. function showFlightInfo(data){
  12. var flightNoEle = document.createElement('h4');
  13. flightNoEle.innerHTML=data.flightNo;
  14.  
  15. var fromEle = document.createElement('h4');
  16. fromEle.innerHTML=data.from;
  17.  
  18. var toEle = document.createElement('h4');
  19. toEle.innerHTML=data.to;
  20.  
  21. document.body.appendChild(flightNoEle);
  22. document.body.appendChild(fromEle);
  23. document.body.appendChild(toEle);
  24. }
  25. </script>
  26. <script src="http://localhost:3001/info/flight?flightNo=MU531&amp;callbackFunc=showFlightInfo"></script>
  27. </body>
  28. </html>

跨域服务器的后台代码中响应JS请求,生成一串使用document.write向页面中生成html元素的字符串。

  1. router.get('/ad', function (req, res) {
  2. //拼接一JS字符串,完成向html页面中输出html标记
  3. var s = 'document.write(\'<div style="background-color:red;width:10rem;height:10rem">我是旅行社广告</div>\');';
  4. console.log(s);
  5.  
  6. res.setHeader('content-type', 'text/javascirpt;charset=utf-8');
  7. res.write(s);
  8. res.end();
  9. });

运行后,浏览器访问本地服务器上的页面,会在航班信息下方显示红色广告位,而这个广告位完全是跨域服务器生成的并且包括样式。

在此基础上,可以做出很多效果,包括将页面某一部分的生成交给专门的或者对应的业务服务器上完成。

说一说javascript跨域和jsonp的更多相关文章

  1. jQuery(三) javascript跨域问题(JSONP解决)

    加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...

  2. javascript 跨域问题 jsonp

    转载:http://www.cnblogs.com/choon/p/5393682.html demo 用动态创建<script></script>节点的方式实现了跨域HTTP ...

  3. 关于javascript跨域及JSONP的原理与应用

    同源策略,它是由Netscape提出的一个著名的安全策略,现在所有的可支持javascript的浏览器都会使用这个策略. 为什么需要同源策略,这里举个例子: 假 设现在没有同源策略,会发生什么事情呢? ...

  4. 利用javascript跨域访问cookie之广告推广

    在上一篇<说一说javascript跨域和jsonp>中,利用JSONP进行了跨域的数据访问,利用JS本身的跨域能力在远端生成HTML结构的方式完成了一个小广告. 在实际应用中, 跨域使用 ...

  5. JavaScript 跨域漫游

    前言: 最近在公司做了几个项目都涉及到了iframe,也就是在这些iframe多次嵌套的项目中,我发现之前对iframe的认识还是比较不足的,所以就静下心来,好好整理总结了iframe的相关知识:&l ...

  6. Javascript跨域问题总结

    疯狂的JSONP 关于JSON与JSONP简单总结 window.name实现的跨域数据传输 JavaScript跨域总结与解决办法 flash跨域策略文件crossdomain.xml配置详解

  7. JavaScript 跨域:window.postMessage 实现跨域通信

    JavaScript 跨域方式实现方式有很多,之前,一篇文章中提到了 JSONP 形式实现跨域.本文将介绍 HTML5 新增的 api 实现跨域:window.postMessage . 1 othe ...

  8. thinkphp,javascript跨域请求解决方案

    javascript跨域请求解决方案 前言 对于很多前端或者做混合开发的同学,我们难免会遇到跨域发起请求业务,比如A站点向B站点请求数据等等.由于最近要做一个站点集群的项目,所以具体业务要求很多个站点 ...

  9. JavaScript 跨域之 POST 实现。

    javascript 跨域是一个很常见的问题,其中 jsonp 是一个最常用的手段,但是 jsonp 只支持 get,不支持 post,所以如果想通过 jsonp 来 post 一些数据,就头大了. ...

随机推荐

  1. jQuery.Ajax IE8 无效(CORS)

    今天在开发的时候,遇到一个问题,$.get()在 IE8 浏览器不起作用,但 Chrome,Firefox 却是可以的,网上资料很多,最后发现是 IE8 默认不支持 CORS 请求,需要手动开启下: ...

  2. 你真的会玩SQL吗?之逻辑查询处理阶段

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  3. Android Studio分类整理res/Layout中的布局文件(创建子目录)

    res/layout中的布局文件太杂,没有层次感,受不了的我治好想办法解决这个问题. 前几天看博客说可以使用插件分组,可惜我没找到.知道看到另一篇博客时,才知道这个方法不能用了. 不能用插件,那就手动 ...

  4. 手机游戏渠道SDK接入工具项目分享(二)万事开头难

    一般接到任务后程序员们通常都开始着手进行技术调研了,但我这活是项目负责人.还有一大堆事情要先期准备,没人能帮忙. 一.人力配置 考虑的之前已经有一波人搞了大半年,但没有起色,先期也没有太大人力需求,所 ...

  5. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  6. 将MPM雪模拟移植到Maya

    同事实现了一个迪士尼的MPM雪模拟论文,我将其移植到Maya中 论文题目是 A material point method for snow simulation 代码在这里: https://git ...

  7. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  8. Asp.Net跨平台:Ubuntu14.0+Mono+Jexus+Asp.Net

    Asp.Net跨平台的文章园子里有很多,这里给自己搭建的情况做一下总结,方便以后查看. 参考网站:   http://www.linuxdot.net/(Linux DotNET大本营 )  http ...

  9. 一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  10. CSS垂直居中总结

    工作中遇到垂直居中问题,特此总结了一下几种方式与大家分享.本文讨论的垂直居中仅支持IE8+ 1.使用绝对定位垂直居中 <div class="container"> & ...