子资源完整性SRI简介

子资源完整性(SRI)是一种确保浏览器从CDN加载的资源未被篡改的安全机制。通过对比资源的哈希值,浏览器判断其是否被修改。当哈希值不匹配时,浏览器将阻止执行,提供错误恢复机制。SRI可以结合内容安全政策(CSP)使用,以增强网页的安全性。然而,仅依赖SRI可能无法完全解决CDN加载失败或网络劫持问题,可能需要配合服务降级和备用源切换策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是SRI

子资源完整性 Subresource Integrity 简称 SRI 是一种安全机制。是允许浏览器检查其获得的资源(例如从 CDN 获得的)是否被篡改的一项安全特性。它通过验证获取文件的哈希值是否和你提供的哈希值一样来判断资源是否被篡改。

在一些CDN网站提供了带SRI的,比如 vue - Libraries - cdnjs ,可以看到如下引用:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.47/vue.cjs.js"
 integrity="sha512-DD31SaA8/u+cn6fBAdPBcABgOkmiogzhPd/dNHvkMmazQLEjiaT9ZP51rkGTpFcx+jFl0EeNCxgxLaNniutt2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

使用子资源完整性功能的方法是,在任何 <script><link> 元素的 integrity 属性值中,指定你要告诉浏览器所获取的资源(或文件)的 base64 编码的加密哈希值。

integrity 值至少由一个字符串开始,每个字符串包括一个前缀,表示一个特定的哈希算法(目前允许的前缀是 sha256sha384sha512),后面是一个短横线(-),最后是实际的 base64 编码的哈希。

可以看到引入css也支持:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap-grid.min.css" 
integrity="sha512-JQksK36WdRekVrvdxNyV3B0Q1huqbTkIQNbz1dlcFVgNynEMRl0F8OSqOGdVppLUDIvsOejhr/W5L3G/b3J+8w==" crossorigin="anonymous" referrerpolicy="no-referrer" />

错误恢复

  1. 当浏览器遇到一个带有 integrityscriptstyle 标签,在执行其中的 JS 脚本或应用其中的 CSS 样式之前,浏览器会首先计算所下载文件的内容的哈希值是否与 integrity 属性给定的值相同。
  2. 如果计算结果与给定值不匹配,浏览器会拒绝执行脚本内容,并报出一个网络错误,类似如下结果:

Failed to find a valid digest in the ‘integrity’ attribute for resource ‘https://cdnjs.cloudflare.com/ajax/libs/normalize/6.0.0/normalize.min.css’ with computed SHA-256 integrity ‘VbcxqgMGQYm3q8qZMd63uETHXXZkqs7ME1bEvAY1xK8=’. The resource has been blocked.

js的判断加载失败从本站加载:

<script src="https://code.jquery.com/jquery-3.2.1.min.js"
        integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f"
        crossorigin="anonymous"></script>
<script>if (!window.jQuery) document.write('<script src="/jquery-3.2.1.min.js"><\/script>')</script>

这其实是一种的服务降级方案,但是这个方案不算完整,比如css就不太容易判断和做降级。

不过一般出现加载失败,除了引用三方站点资源发生了篡改,还有可能是三方服务或网络问题导致不可用。可以js重定向到一个本站页面实现降级服务。

if(!window.jQuery) location= 'redirect_url'

CDN加载失败还有可能是被网络劫持了,还有种方式应该可以实现多个CDN或三方备用源切换,通过js加载资源方式。这样还能打点上报故障区域,为故障诊断网站运维提供信息。

var s = document.createElement('script');
s.crossOrigin = 'anonymous';
s.integrity="sha384-xxxxx";
s.onerror = function() {
  // 打点上报劫持数据 (这里是用img src上报)
  var img = document.createElement('img');
  img.src = 'http://xxx.com?url='+s.src;
  document.body.appendChild(img);

  // 更换其他域名下载地址
  s.src = 'http://zeptojs.com/zepto.min.js';  
};
s.onload = function() {
  console.log($);
}
s.src = 'http://lib.baomitu.com/zepto/1.2.0/zepto.min.js';
document.head.appendChild(s);

CSP与SRI

你可以使用 内容安全政策CSP)强制要求当前页面所有脚本加载标签启用 SRI。例如

Content-Security-Policy: require-sri-for script;

强制要求所有 script 标签启用 SRI,浏览器会拒绝加载未启用 SRI 的 script 标签。

对应的还有 CSS 版本:

Content-Security-Policy: require-sri-for style;

你也可以同时启用两者。

参考:

子资源完整性 - Web 安全 | MDN

html - 使用SRI保护你的网站免受第三方CDN恶意攻击 - SegmentFault 思否

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值