CSP(Content-Security-Policy)是一个HTTP response header, 它描述允许页面控制用户代理能够为指定的页面加载哪些资源, 可防止XSS攻击
使用方式:
Content-Security-Policy: 指令1 指令1的值1 指令1的值2 指令1的值3; 指令2 指令2的值1 指令2的值2 复制代码调试工具: Chrome插件——modheader。通过随意设置响应头来测试CSP 简单过一遍常见的指令 获取资源相关的指令
font-src frame-src img-src script-src media-src style-src ...等等,其他参考MDN 复制代码这些src规定了页面只能加载里面所设置的font、iframe、img、script... 这些资源,比如有一个html页面的response header是:
Content-Security-Policy: img-src a.b.c; script-src 'unsafe-inline' a.b.c; style-src 'self' 复制代码表示只能加载来自 a.b.c 域的图片、a.b.c 域的脚本和行内脚本(如 <script>console.log(1)</script> )、只能加载自己域下的style
这些xx-src,一般常见的配置有:
host配置
可精确匹配也可通配符匹配:
https://*.qq.com https://a.b.com *.qq.com www.qq.com 复制代码最后,有一个通用化配置——default-src,你给了它什么值,其他几个指令就默认什么值。其他指令如果有设置,那自身的值会覆盖 default-src的值
schema配置
data: => dataURI,比如base64 blob: => blob资源 http: => 顾名思义 https: => 顾名思义 ...一般是这些比较多,其他参考MDN 复制代码注意,要写冒号。为了防止误解,所以上面用=> 描述了。eg:
Content-Security-Policy: img-src http: data:; style-src 'self' 复制代码self
只能加载自身相同的域资源,其他如 data: ,blob: 就不能了
unsafe-inline行内,一般针对于style和script标签。没有这个,就不能使用行内标签了
上报指令 如果设置了上报指令的上报地址,当页面有加载不合法的资源,将会往那里上报。比如
Content-Security-Policy: img-src www.qq.com; report-uri https://a.b.c/report 复制代码当设置这个header的页面加载www.qq.com之外的图片的时候,将会阻塞加载,并在控制台报错,再上报到 https://a.b.c/report上 上报的数据就是这些,浏览器帮你拼装好了。当然,随便写的路径肯定是404的,这个自己起一个服务器就可以收到这个上报
目前阶段,一般使用report-uri上报,用法是后面接上上报地址。 report-to 是另一个上报指令,功能更丰富,使用方式稍微麻烦一点
Content-Security-Policy: report-uri https://a.b.c/report Content-Security-Policy: report-uri /current_page_report 复制代码其他的指令比较简单,但使用场景可能不是很多,有兴趣去MDN看看
CSP如何在自己前端项目落地 第一阶段 使用 Content-Security-Policy-Report-Only头而不是直接使用Content-Security-Policy 。 Content-Security-Policy-Report-Only 顾名思义,只是上报,不会阻塞资源加载。因此页面改造第一步是先通过仅仅上报的头来观察一段时间,看看哪些资源哪些case是不符合CSP的,漏掉的加上,不合理的干掉
初始化资源指令,给 default-src 一个'self' ,让资源都默认走本地。其次通过其他方式改变header(我使用了浏览器插件的方式,比较简单暴力。其实还可以自己开个服务器做代理、本地起nginx加头等等方式都可以),观察控制台报错,再把漏掉的资源补齐,如cdn站点、base64的data:、第三方sdk、图片cos存储地址等都是最常见的case
补齐资源,让页面不再报错;一些是不太优雅或者有风险的case,自己再另外衡量要不要换另一种方式引入或者去掉
另外,如果有iframe、worker、websocket这些的,也需要配置一下CSP
第二阶段 观察一段时间后,自己的上报站点如果有CSP报错,那么去解决掉,然后继续观察一段时间重复同样的步骤,直到没有CSP错误。当上报站点再也没有CSP错误或者错误比较少能接受范围内,将 Content-Security-Policy-Report-Only 换成Content-Security-Policy 再次上线
线上不可能也要人家装插件啊、代理啊,如何修改这个头
一般页面就在nginx上对html配response header
location ~* .(html)$ { add_header Content-Security-Policy "img-src http: data:; style-src 'self'"; } 复制代码如果是ssr项目或者前后端不分离项目,服务端直接setheader即可
如果是新需求可能涉及到新的资源引入怎么办
确定知道的源,新增header配置;不确定的最好自己设置一个中转服务,或者重新思考一下需求/技术方案合理性;实在没办法,需要删除default-src设置,并且img-src需要妥协一下了
如果有新页面上线且旧页面已经不使用report-only了怎么办
nginx配置一下,不同的页面使用不同的头
location /a { add_header Content-Security-Policy "img-src http: data:; style-src 'self'"; } location /b { add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri https://a.b.c/report"; } 复制代码服务端的话,判断一下页面路径,采用不同的setheader方式
如果你现在也想学习前端开发技术,在学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,你都可以加入到我的Q群中:前114中6649后671,里面有许多前端学习资料以及2020大厂面试真题 点赞、评论、转发 即可免费获取,希望能够对你们有所帮助。