说说 JSONP 和 XSS
我讨厌 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。
解决方法
- 就是前面说到的,Content-Type 不要乱用,严格按照标准协议来做。目前的框架默认肯定会检测一下内容类型,如果不是很必要,不要手动设置。因为有可能多转发几次 Content-Type 就被改了。
- callback 做长度限制,这个比较 low。
- 检测 callback 里面的字符。一般 callback 里面都是字母和数字,别的符号都不能有。
-
callback 做一个编码,如果用 Go 语言做的话,如下。对所有 callback 都处理。
callback = template.JSEscapeString(callback)
完整代码可以参考这里。
原文链接:说说 JSONP 和 XSS,转载请注明来源!
–EOF–