SRI 介绍

SRI 是什么?
SRI 是 Subresource Integrity 的缩写,一般按照字面意义翻译为:子资源完整性(草案),它也是由 Web 应用安全工作组(Web Application Security Working Group)发布。

Web 性能优化中很重要的一点是让请求提前结束,让可缓存的资源走 CDN 是最通用的做法。CDN 服务提供商通过分布在各地的节点,让用户从最近的节点加载内容,大幅提升速度。但是 CDN 的安全性一直是一个风险点:对于网站主来说,让请求从第三方服务器经过,由第三方响应,安全方面肯定不如自己服务器可控。

我们知道 CSP(Content Security Policy) 的外链白名单机制可以在现代浏览器下减小 XSS 风险。但针对 CDN 内容被篡改而导致的 XSS,CSP 并不能防范,因为网站所使用的 CDN 域名,肯定在 CSP 白名单之中。这时候,SRI 就应运而生了。它通过对资源进行摘要签名机制,来保证外链资源的完整性(不被篡改)。

目前支持 SRI 的浏览器有 Chrome 45+ 和 FireFox 43+。IE Edge 表示考虑中,将其列入了需求池,接受用户投票。CanIUse 网站目前尚未提供 SRI 支持度数据,但是已经有人提了 Issue,后续应该会加上。

启用 SRI 策略后,浏览器会对资源进行 CORS 校验,这就要求被请求的资源必须同域,或者配置了 Access-Control-Allow-Origin 响应头。这个细节需要大家注意。

要使用 SRI,只需要在原有的标签里增加 integrity 属性即可,这个属性的签名算法支持 sha256、sha384 和 sha512,签名算法和摘要签名内容用 - 分隔。例如,要引入以下这个资源,并启用 SRI 策略: https://example.com/static/js/other/zepto.js

可以使用 sha256 算法生成摘要签名,并进行 Base64 编码:

        curl https://example.com/static/js/other/zepto.js | openssl dgst -sha256 -binary | openssl enc -base64 -A

        b/TAR5GfYbbQ3gWQCA3fxESsvgU4AbP4rZ+qu1d9CuQ=
    

生成的结果就是 integrity 属性后边的值,属性值前面跟的是 生成算法的类型。

        script type="application/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"

        integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"
    

浏览器拿到资源内容之后,会使用 integrity 所指定的签名算法计算结果,并与 integrity 提供的摘要签名比对,如果二者不一致,就不会执行这个资源。

动态加载的资源使用 SRI 也是类似的,需要指定 crossOrigin(注意大小写)和 integrity 属性。例如:

        
            var s = document.createElement('script');
            s.crossOrigin = 'anonymous';
            s.integrity = 'sha256-b/TAR5GfYbbQ3gWQCA3fxESsvgU4AbP4rZ+qu1d9CuQ=';
            s.src = 'https://example.com/static/js/other/zepto.js';
            document.head.appendChild(s);
        
    

在加载 CSS 资源启用 SRI,使用 Fetch Api 时启用 SRI,都是类似的,这里略过。

转自:Subresource Integrity 介绍