27 October 2017

IMG-THUMBNAIL

我讨厌 JSONP

JSONP

先说 JSONP。通过 JavaScript 调用,被调用域名和当前页面域名不一致,就需要用到 JSONP。不过我不太推荐这么跨域调用。

如果真的要解决跨域问题,我觉得有几个不错的方法,一个是两组服务器配上相同的域名。还有就是自己的服务器 nginx 上做一个转发。

XSS

跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。

上面是维基百科的解释。实际一点的例子可以看看我文本的头图。页面被注入了一张图片。恶意的注入可以注入一段脚本。

问题原因

浏览器为了保证跨域访问的安全性,会默认发一个 callback 参数到后台,接口拿到这个参数之后,需要将返回的 JSON 数据外面包上 callback 参数。

具体的返回格式:

CALLBACK(JSON)

如果 ajax 请求是 JSONP 请求,返回的内容浏览器还会自动检测,如果不是按这个格式返回或者 callback 的内容不对,这次请求就算失败了。

这里有一个机制,那就是请求的 callback 会被放入返回的内容当中,这也是可能出问题的地方。

支持 JSONP 的链接如果直接放到浏览器里面访问,浏览器就不会做 callback 校验了。

Content-Type: application/json

浏览器渲染就是靠 Content-Type 来做的。如果返回内容标记是 json,哪怕 body 里面都是 html 的标签,浏览器也不会渲染。所以,如果接口返回的不是 html,千万不要写成 html。

Content-Type: text/html

如果返回的内容是页面,html类型。那么 callback 注入的 html 元素都可以直接放到页面上了。那么,html 页面必然不能支持 callback。

解决方法

  1. 就是前面说到的,Content-Type 不要乱用,严格按照标准协议来做。目前的框架默认肯定会检测一下内容类型,如果不是很必要,不要手动设置。因为有可能多转发几次 Content-Type 就被改了。
  2. callback 做长度限制,这个比较 low。
  3. 检测 callback 里面的字符。一般 callback 里面都是字母和数字,别的符号都不能有。
  4. callback 做一个编码,如果用 Go 语言做的话,如下。对所有 callback 都处理。

    callback = template.JSEscapeString(callback)

完整代码可以参考这里


原文链接:说说 JSONP 和 XSS,转载请注明来源!

EOF