← 中文资源

简体中文版本

crypto.subtle 为 undefined — 需要安全上下文

通过改用 HTTPS 或 localhost 提供服务,修复 crypto.subtle 为 undefined——Web Crypto 仅限安全上下文。

阅读英文原文

症状

本篇调试指南针对“crypto.subtle 为 undefined — 需要安全上下文”。内容涵盖可观察的症状、可复现的诊断路径、根本原因、具体修复方式,以及如何验证修复并防止回归。

可观察到的症状包括:

  • TypeError: 无法读取 undefined 的属性(读取 digest)
  • Web Crypto 本地可用,预发服务器不可用
  • 以纯 http:// 提供的应用无法哈希或加密

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

console.log(window.isSecureContext, window.crypto?.subtle)

isSecureContext 为 false 或 subtle 为 undefined,即确认是环境而非代码问题。

步骤 2

openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 1

快速生成自签证书即可使源变为安全,subtle 随之可用。

常见诱因(按出现频率排序):

  • 页面非安全上下文(非 localhost 的 HTTP 源)
  • 未做特性检查就访问 window.crypto.subtle
  • 旧版或内置浏览器不支持 Web Crypto

根因

Web Crypto 仅在安全上下文(HTTPS、localhost 或 file)中暴露 crypto.subtle。在不安全源上,window.crypto 仅供 getRandomValues,subtle 为 undefined,调用即抛错。

修复

在所有非本地环境用 HTTPS 提供服务,使用前探测 crypto.subtle,并在该 API 不可用时提供服务端回退。

注意:为安全目的回退到非加密哈希很危险;仅在非安全用途时回退。

if (window.isSecureContext && window.crypto?.subtle) {
  const enc = new TextEncoder();
  const hash = await crypto.subtle.digest('SHA-256', enc.encode('data'));
  console.log([...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, '0')).join(''));
} else {
  // secure context required; fall back or ask the user to use HTTPS
  console.warn('crypto.subtle unavailable: secure context required');
}

验证

通过 HTTPS 加载并确认 isSecureContext 为 true 且 crypto.subtle.digest 成功;测试 HTTP 源仍给出清晰回退提示。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。