HTTP传输中使用CSP防劫持插广告的方法

万恶的运营商,不定期地在我们浏览的网页里插广告已经是公开的秘密了。最有效的防运营商劫持方法当然是HTTPS传输,但是受服务器限制,或者大量图片等内容需要使用HTTP传输,HTTPS有时候并不容易实现。

今天发现了个有用的东西:Content Security Policy,简称CSP,它可以指定浏览器加载或执行哪些资源(包括css、js、图片、字体等),未指定的资源会被屏蔽。

这样,如果运营商在我们的网页里面插入了广告代码,但其引用的js域名并未在CSP中列出,浏览器就不会让这个广告显示出来了。知乎就是用了这种方法。

比如我只想允许自己的域名以及cdn.qifu.me中的css、js、图片资源被加载,就可以在HTTP头信息中加入以下规则:

Content-Security-Policy:default-src 'self' cdn.qifu.me

如果利用.htaccess配置的话,添加下面一行即可:

Header set Content-Security-Policy "default-src 'self' cdn.qifu.me"

如果你怕运营商劫持过程中替换掉你的http header导致上述信息被抹除,可以在html代码中的head标签内加入下面的内容:

<meta http-equiv="Content-Security-Policy" content="default-src 'self' cdn.qifu.me" />

这里我用了最简单的默认指令default-src,其实后面还可以添加更多细化的指令,比如style-src、script-src、img-src、media-src、font-src等等,多个指令之间用分号隔开。每条指令后面跟空格,列出该指令允许的资源值,多个资源用空格隔开。’self’代表同源内容,也可以指定某个域名,甚至使用通配符,比如*.qifu.me,还可以包含协议和端口,或者用https:代表所有的HTTPS资源,当然,你也可以写’none’禁止所有。

需要注意的是,上面这么写,所有的内联资源都失效了,也就是说标签内添加的style和js都不会被执行,如下所示,文字既不是红色,onclick代码也不会被执行。这样是最安全的,但是如果需要,可以加入’unsafe-inline’,类似于“default-src ‘self’ ‘unsafe-inline’ cdn.qifu.me”这样。

<p style="color:#f00;" onclick="alert('Hello from Qifu');">我不是红色,点我也没有问候</p>

与上述类似,不加’unsafe-eval’的话,所有的new Function、setTimeout、eval等动态js代码也不会被执行。但是,这些很少用到,建议不要加!

这种方法,亲测Edge和Chrome48都是可以的,但是IE11不行,即使用“X-Content-Security-Policy”也不行,因为IE只是部分支持’sandbox’指令;老版的Safari和IE类似,使用非标准的“X-Webkit-CSP”,这俩非标都不建议使用,因为支持不完整或者有bug。所以强烈建议所有人升级最新版的浏览器,不要以能用就行的态度死守老版本,升级、试一下~

感兴趣的可以试一下,一定要注意包含自己引用的所有资源,比如google字体、js、cdn之类的。

随便看看

本文共有27条评论

你好,哪位? 填写