SRI

SRI

介绍

SRISubresource Integrity,子资源完整性)是一项安全性功能,浏览器借助该功能可以验证资源是否被篡改。

具体原理是通过给 link 标签或 script 标签增加 integrity 属性开启 SRI 功能。integrity 属性包含两部分内容:前者是指定哈希算法,可以是 sha256sha384sha512;后者通过指定的哈希算法对资源内容进行 Hash 处理,并对哈希结果进行 Base64 编码,得到摘要内容。哈希算法和摘要内容通过 - 进行拼接。

1
2
3
4
5
6
7
<script src="https://example.com/example-framework.js"
integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
crossorigin="anonymous"></script>

<link rel="stylesheet" href="https://site53.example.net/style.css"
integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"
crossorigin="anonymous">

浏览器获取资源后,会根据 integrity 指定的哈希算法进行哈希计算,并将计算结果与 integrity 值进行对比。如果两者一致,则执行资源内容,反之则不执行。

Github 在 2015 就开启了 SRI 功能

另外有一点需要注意的是:启用 SRI 后,浏览器在解析 integrity 属性前会对应的资源进行 CORS 校验;这意味着请求资源需与页面同域,或者配置 Access-Control-Allow-Origin 响应头。

用途

在日常开发中,通常会借助 CDN 来减少请求时间,但 CDN 资源位于第三方服务器中,资源的安全性不完全可控。如果发生 CDN 劫持或被运营商劫持,很容易导致资源被篡改。

SRI 的作用是确保页面引入第三方资源的完整性,如果开启 SRI,那么可以确保被篡改的资源无法执行。

但 SRI 并非无懈可击,如果将整个 HTML 和第三方资源一起劫持,那么 SRI 就失效了。另外,开启 SRI 后,被篡改的资源无法执行,很容易导致页面不可用,需要考虑相应的 Plan B。

用法

在 Webpack 中可以借助 webpack-subresource-integrity 插件来生成哈希摘要

1
2
3
4
5
const SRIPlugin = require('webpack-subresource-integrity');

plugins: [
new SRIPlugin({ hashFuncNames: ['sha256', 'sha384'] }),
]
1
2
3
4
5
<script type="text/javascript" src="vendor.chunk.js" integrity="sha256-MoK6dWXV6uQlfee2NzIP8ZACIzoRhaEQzN8EGNUyxWE= sha384-eiRYBz2W/PGzdYT6oL6PwiWMQVRMHHZmscR3/uWB0o2EzJFKUfzjL1p5WBPmLikA" crossorigin="anonymous"></script>

<script type="text/javascript" src="polyfills.bundle.js" integrity="sha256-OxYlbuMdFXS/Hm/B02t0XHX/ssUBECtu3hlPgYpzz1E= sha384-opPBggjah9dXA7ZyQYvXBDDSB6zmkE+BQ6mbHALnt+gOWc4cz60x11fP83p6dArb" crossorigin="anonymous"></script>

<script type="text/javascript" src="main.bundle.js" integrity="sha256-t+miQ+xpPl2nY84ZMMl7DDd9qArjJBmZuFbd/kh4eXg= sha384-mF0CNxFWpVfgyOG7XD2GoWHJ54DlKN3udLZab9/ir8VTAMPbUXildN4T2h7VdmZn" crossorigin="anonymous"></script>

参考