各位观众老爷,晚上好! 今天咱们聊聊一个听起来高大上,但其实挺接地气的技术 – Subresource Integrity (SRI),中文名叫“子资源完整性”。 别被这名字吓着,它就是个给 CDN 脚本加保险的东东。 咱们的目标是,保证你从 CDN 拉来的脚本,真的是你想要的那个,没被中间人篡改过。
第一部分:CDN 脚本的安全隐患,细思极恐啊!
先问个问题:你网站上的 jQuery 是从哪儿来的? Bootstrap 是从哪儿来的? 估计大部分人都是直接用 CDN 链接,比如:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
看起来很美好,速度快,省流量。但是!这里面藏着一个巨大的安全隐患。 如果 CDN 被黑了,或者中间人攻击,你的 jQuery 被替换成了恶意代码,那你的网站就被别人随意摆弄了。想象一下,你的用户在你的网站上输入密码,然后密码被偷偷发到了黑客的服务器上… 细思恐极啊!
- CDN 被黑: 这事儿不是没发生过。曾经就有 CDN 服务商被入侵,导致大量网站受到影响。
- 中间人攻击: 在不安全的网络环境下(比如公共 Wi-Fi),黑客可以截获你的网络请求,然后把 CDN 链接指向他自己的服务器,返回恶意代码。
- CDN 内部人员作恶: 这个可能性虽然小,但也不是没有。
第二部分:SRI 出场,闪亮登场!
SRI 就是为了解决这个问题而生的。 它的原理很简单:给每个 CDN 资源生成一个唯一的指纹(哈希值),然后把这个指纹放到 HTML 标签里。 浏览器在加载资源的时候,会比对下载下来的资源的哈希值和 HTML 标签里的哈希值,如果不一样,就拒绝执行这个脚本。 相当于给 CDN 脚本加了一个数字签名,确保你拿到的是原汁原味的,没有被篡改过的。
具体怎么用呢? 咱们还是拿 jQuery 举例子。 首先,你需要生成 jQuery 文件的哈希值。 你可以用 openssl
命令,或者在线的 SRI hash 生成工具。 这里我们假设你已经生成了如下哈希值:
sha384-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
然后,把这个哈希值放到 <script>
标签的 integrity
属性里:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"
integrity="sha384-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
crossorigin="anonymous"></script>
注意 crossorigin="anonymous"
这个属性。 它告诉浏览器,这个资源是从其他域名加载的,需要使用 CORS (跨域资源共享) 来获取资源。 SRI 和 CORS 是配合使用的,少了 CORS,SRI 可能不起作用。
重点来了!哈希算法的选择!
integrity
属性的值是由哈希算法和哈希值组成的。 哈希算法有很多种,常用的有 sha256
、sha384
和 sha512
。 理论上,哈希算法越复杂,安全性越高。 但是,哈希算法越复杂,计算量也越大,会稍微影响性能。 一般来说,sha384
是一个不错的选择,兼顾了安全性和性能。 所以,推荐使用 sha384
。
如果哈希值不匹配怎么办?
如果浏览器检测到下载的资源的哈希值和 integrity
属性里的哈希值不匹配,浏览器会拒绝执行这个脚本,并且会在控制台输出错误信息。 你的网站不会崩溃,但是依赖这个脚本的功能就不能用了。 所以,你需要监控你的网站,及时发现 SRI 错误,然后更新 integrity
属性里的哈希值。
第三部分:SRI 的优势,优点多多!
- 防篡改: 这是 SRI 最主要的功能,保证你加载的 CDN 资源没有被篡改过。
- 提升安全性: SRI 可以有效防止 XSS (跨站脚本攻击) 攻击。 即使攻击者成功注入了恶意脚本,如果这个脚本的哈希值和
integrity
属性里的哈希值不匹配,浏览器也会拒绝执行这个脚本。 - 增强用户信任: 使用 SRI 可以让用户更加信任你的网站,因为你采取了额外的安全措施来保护他们的数据。
- 简单易用: SRI 的使用非常简单,只需要生成哈希值,然后放到 HTML 标签里就可以了。
- 兼容性好: SRI 的兼容性非常好,主流浏览器都支持。
第四部分:SRI 的不足,并非万能!
SRI 虽然好,但也不是万能的。 它也有一些局限性:
- 需要维护: 如果 CDN 资源更新了,你需要重新生成哈希值,然后更新
integrity
属性。 这是一个重复性的工作,需要人工维护。 如果你的网站有很多 CDN 资源,维护起来会比较麻烦。 - 只保护完整性: SRI 只保证资源的完整性,不保证资源的可用性。 如果 CDN 挂了,或者资源被删除了,SRI 也无能为力。
- 不能防止所有类型的攻击: SRI 只能防止 CDN 资源被篡改。 如果攻击者直接攻击你的服务器,或者利用其他漏洞,SRI 就起不了作用了。
- 哈希值的生成和管理: 手动生成和管理哈希值比较繁琐,容易出错。 需要使用工具或者脚本来自动化这个过程。
- 不支持动态资源: SRI 不支持动态生成的资源。 因为动态生成的资源的哈希值每次都不一样,无法预先放到 HTML 标签里。
- CORS 依赖: SRI 依赖 CORS。 如果 CORS 配置不正确,SRI 可能不起作用。
- 性能影响: 虽然 SRI 的性能影响很小,但是浏览器需要计算资源的哈希值,会增加一点点加载时间。
- CDN 自身安全问题: SRI 无法解决 CDN 自身的安全问题,例如 CDN 提供商内部人员的恶意行为。
表格总结 SRI 的优缺点:
特性 | 优点 | 缺点 |
---|---|---|
功能 | 防篡改,提升安全性,增强用户信任 | 需要维护,只保护完整性,不能防止所有类型的攻击,不支持动态资源,CORS 依赖,存在一定的性能影响,无法解决 CDN 自身安全问题 |
易用性 | 简单易用 | 哈希值的生成和管理比较繁琐 |
兼容性 | 兼容性好 | – |
安全性 | 有效防止 CDN 资源被篡改,防止 XSS 攻击 | – |
性能 | 影响小 | 计算哈希值会增加一点点加载时间 |
应用场景 | 适合静态 CDN 资源,例如 JavaScript 库、CSS 样式表、字体文件等。 | 不适合动态生成的资源,例如 API 接口返回的数据。 |
第五部分:SRI 的最佳实践,照着做就对了!
- 使用 SRI: 无论如何,都应该使用 SRI 来保护你的 CDN 资源。 这是一种简单有效的安全措施。
- 选择合适的哈希算法: 推荐使用
sha384
。 - 使用自动化工具: 使用工具或者脚本来自动化生成和管理哈希值的过程。 有很多现成的工具可以使用,例如
srihash
、webpack-subresource-integrity
等。 - 监控 SRI 错误: 监控你的网站,及时发现 SRI 错误,然后更新
integrity
属性里的哈希值。 可以使用 Sentry、Bugsnag 等错误监控工具。 - 配合 CORS 使用: 确保 CORS 配置正确,否则 SRI 可能不起作用。
- 定期更新哈希值: 当 CDN 资源更新时,及时更新
integrity
属性里的哈希值。 - 不要只依赖 SRI: SRI 只是安全措施的一部分,还需要采取其他安全措施来保护你的网站,例如使用 HTTPS、防止 SQL 注入、防止 XSS 攻击等。
- 考虑使用内容安全策略 (CSP): CSP 是一种更强大的安全机制,可以控制浏览器可以加载哪些资源。 CSP 可以和 SRI 配合使用,进一步提升网站的安全性。
代码示例:使用 srihash
工具生成哈希值
首先,安装 srihash
工具:
npm install -g srihash
然后,使用 srihash
命令生成哈希值:
srihash jquery.min.js --algorithm sha384
这个命令会输出 jQuery 文件的 sha384
哈希值。 然后,把这个哈希值放到 <script>
标签的 integrity
属性里。
代码示例:使用 Webpack 插件 webpack-subresource-integrity
如果你的项目使用了 Webpack,可以使用 webpack-subresource-integrity
插件来自动生成哈希值,并添加到 HTML 标签里。
首先,安装 webpack-subresource-integrity
插件:
npm install webpack-subresource-integrity --save-dev
然后,在 webpack.config.js
文件里配置插件:
const SriPlugin = require('webpack-subresource-integrity');
module.exports = {
// ...
plugins: [
new SriPlugin({
hashFuncNames: ['sha384'], // 使用 sha384 算法
enabled: true, // 开启 SRI
}),
],
};
然后,运行 Webpack 构建命令:
npm run build
Webpack 会自动生成哈希值,并添加到 HTML 标签里。
第六部分:SRI 的未来发展趋势,拭目以待!
- 自动化程度更高: 未来的 SRI 工具会更加自动化,可以自动检测 CDN 资源的变化,然后自动更新
integrity
属性里的哈希值。 - 与 CSP 结合更紧密: SRI 和 CSP 会更加紧密地结合在一起,共同提升网站的安全性。
- 支持更多类型的资源: SRI 会支持更多类型的资源,例如图片、字体文件等。
- 性能优化: 未来的 SRI 技术会更加注重性能优化,减少对网站加载速度的影响。
第七部分:总结,敲黑板划重点啦!
SRI 是一种简单有效的安全措施,可以保护你的 CDN 资源免受篡改。 虽然 SRI 不是万能的,但是它仍然是一个值得使用的技术。 记住,安全无小事,不要放过任何一个可以提升网站安全性的机会。
最后,给大家留个小作业:
- 检查你的网站是否使用了 SRI。
- 如果你的网站没有使用 SRI,请立即启用它。
- 使用自动化工具来生成和管理哈希值。
- 监控 SRI 错误,及时更新
integrity
属性里的哈希值。
好啦,今天的讲座就到这里,希望对大家有所帮助。 谢谢大家! 祝大家周末愉快,代码无 Bug! 咱们下次再见!