JSONP处理同源策略

跨域网络访问EDIT

同源策略控制了不同源之间的交互,例如在使用XMLHttpRequest 或 <img> 标签时则会受到同源策略的约束。交互通常分为三类:

  • 通常允许进行跨域写操作(Cross-origin writes)。例如链接(links),重定向以及表单提交。特定少数的HTTP请求需要添加 preflight
  • 通常允许跨域资源嵌入(Cross-origin embedding)。之后下面会举例说明。
  • 通常不允许跨域读操作(Cross-origin reads)。但常可以通过内嵌资源来巧妙的进行读取访问。例如可以读取嵌入图片的高度和宽度,调用内嵌脚本的方法,或availability of an embedded resource.

以下是一些可以跨域内嵌的资源示例:

  • <script src="..."></script>标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
  •  <link rel="stylesheet" href="...">标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type消息头。不同浏览器有不同的限制: IEFirefoxChromeSafari (跳至CVE-2010-0051)部分 和 Opera
  •  <img>嵌入图片。支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,...
  •  <video> 和 <audio>嵌入多媒体资源。
  •  <object><embed> 和 <applet>的插件。
  • @font-face引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。

  •  <frame> 和 <iframe>载入的任何资源。站点可以使用X-Frame-Options消息头来阻止这种形式的跨域交互。
  • ---------------------------------------------------------------------------------------------------------------------------------------
  • 0x00 前言

    关于JSONP网上有很多文章了,我也是在拜读了别人的文章的基础上来写写自己的看法,这样可以加深自己印象,巩固一下学习效果。我们需要做的就是站在巨人的肩膀上眺望远方。

    0x01 起

    在Web前端开发中有一种安全机制,Javascript脚本只能访问与它同域的内容,这就是同源策略。
    这里就需要先说明一个问题:如果确定脚本的域?

    html页面中试用脚本有两种方式:内联和引用。

    上图中滑红框部分,src为引用方式,直接在script中写代码是内联方式。
    如果html的页面url为:http://a.huangjacky.com/a.html,那么内联方式脚本的域是a.huangjacky.com,这应该比较容易理解。
    引用方式有两种情况,引用的js文件就是A站点、引用的js是其他站点,但是不过是内联还是引用方式的脚本代码它执行都是在当前html下,因此它的域是和html相同的

    图中例子用的是AJAX网络请求,其实Javascript访问内容还可以DOM操作,当iframe之间的域不相同时,也无法通过Javascript去操作其他iframe中的DOM元素。

    上面这个还比较基础,老鸟别喷。

    现在开始我们的例子:

    1. 有两个站点a.huangjacky.com, b.huangjacky.com
    2. A站点的a.html要去请求B站点的b.php

    a.html的代码如上图,b.php的代码如下:

    1 <?php
    2 echo"from b site";
    

    我们点击a.html中按钮看一下会是什么样的效果?


    提示说的很清楚,A站的Javascript的XMLHttpRequest对象无法加载B站,因为没有Access-Control-Allow-Origin头,那么接下来我们就来看看这个HTTP头有什么用?

    在跨域HTTP请求中,会有一个HTTP头叫Origin,上图中也可以看出来,响应中HTTP头中的Access-Control-Allow-Origin包含Origin域,那么就满足跨域,浏览器就不会报错了,接下来我们修改PHP代码:

    1 <?php
    2 header("Access-Control-Allow-Origin: http://a.huangjacky.com");
    3 echo"from b site"
    

    代码中就增加一行header设置,看看运行效果:

    运行正常了,AJAX也获得到了B站数据了,但是如果有个C站也要获取B站数据呢?我们分别尝试设置Access-Control-Allow-Orgin为http://huangjacky.comhttp://*.huangjacky.com。都出现了通源策略访问错误的提示,我这里就不截图了,我肯定是试了的。

    现在问题出来了,我就是有这样的需求,多个子域都要访问B站来获取数据,怎么办?

    其实这里可以设置Access-Control-Allow-Orgin: * ,就可以了。

    但是这样安全性又是一个问题了,所有的网站都可以访问来访问数据了,而Access-Control-Allow-Orgin头要么是*,要么指定子域名。其实这里我们可以在PHP中做一些逻辑判断,比如判断Origin头是否huangjacky.com的请求,那么就设置Access-Control-Allow-Orgin为*,不就可以了么?代码如下:

    1 <?php
    2 $origin = $_SERVER['HTTP_ORIGIN'];
    3 if(preg_match('/^http:\/\/\w+\.huangjacky\.com/i',$origin))
    4     header("Access-Control-Allow-Origin: *");
    5 echo"from b site";

    具体其他的参数可以参考附录中的详细文档咯。

    0x02 承

    JSONP也是Web开发中针对跨域提出来一种方法,它不是新技术,反而是一些老技术的整合,这样在浏览器的兼容性上面做得不错。前面我们说到过script标签的src是可以跨域引用js,把js加载到自己的域中来执行。因此我们可以在引用js的同时提交一些参数,这样B站根据参数做出相应的操作后,将操作的结果写入到js文件中,并返回给A站点,这样A站点就得到了B站点的数据了。

    第一框中function是A站在加载完B站数据后执行的函数。第二框是一个DOM中添加一个script标签。因此我们现在有必要看看B站后台是怎么实现的:

    重点是要输出要确定Content-Type,然后就是拼凑javascript代码了。

    是吧很简单的,在jQuery在$.ajax函数中将参数dataType设置成jsonp的话,就会按照这种原理来实现跨域,和XMLHttpRequest没有半毛钱的关系了。

    0x03 转

    从JSONP的原理来看的话,script标签只能GET方式。还有就是后台程序需要对callback参数进行有效性过滤,不然恶意用户可以插入攻击代码了。一般使用正则:

    ^[a-z0-9_]+$

    来判断用户的回调函数名是否合法。

    而JSONP中经常还会遇到一个问题就是JSON劫持,这是CSRF中的一种,常用的防御方式都是部署TOKEN。

    0x04 附录

    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
    2. http://www.ibm.com/developerworks/cn/web/wa-aj-jsonp1/
    3. http://www.nowamagic.net/librarys/veda/detail/224

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值