HTML5的localStorage和sessionStorage本身不加密,数据以明文存储,必须由开发者手动加密(推荐Web Crypto API的AES-GCM模式)并动态派生密钥(如PBKDF2或服务端下发),结构化存储IV、salt、密文等字段,同时严守HTTPS、CSP等基础安全前提。

HTML5 的 localStorage 和 sessionStorage 本身不加密,所有数据以明文形式存储在浏览器中,直接可读。要真正保护敏感内容,必须由开发者在写入前手动加密、读取后手动解密——核心不是“能不能做”,而是“怎么安全地做”。
用 Web Crypto API 做 AES-GCM 加密
这是目前最推荐的方式,现代浏览器原生支持,兼顾安全性与性能,且自带完整性校验(防篡改)。
- 必须使用
AES-GCM模式,禁用 ECB、CBC、MD5、SHA-1 等弱算法或无认证模式 - 密钥长度固定为 256 位(32 字节),通过
crypto.subtle.importKey导入时需明确指定length: 256 - IV(初始化向量)每次加密都得全新生成,长度严格为 12 字节(GCM 推荐值),不可复用、不可预测
- 加密结果是
ArrayBuffer,不能直接存入localStorage,需转成 Base64 或 base64url 编码
密钥不能硬编码,得动态派生
前端无法安全长期保存密钥,任何存在 JS 变量、内存或 Storage 中的密钥都可能被提取。可行方案只有两类:
- 用户口令派生(PBKDF2):用用户输入的密码 + 随机 salt 生成密钥;salt 必须单独存储(如和密文一起存进 localStorage),迭代次数 ≥ 100,000
- 服务端下发临时密钥:登录后,后端用 RSA 公钥加密一个一次性 AES 密钥返回,前端仅在内存中使用,绝不落地
- 绝对不要把密钥写死在代码里、存进 localStorage、或从 URL/cookie 里读取
加密后结构化存储与读取还原
不能只存密文,IV、salt(若使用 PBKDF2)、甚至算法标识都要一并保存,否则解密必然失败。
立即学习“前端免费学习笔记(深入)”;
- 推荐封装成 JSON 对象再存:
{ iv: "base64", data: "base64", salt: "base64" } - 存入前调用
JSON.stringify(),取出后先JSON.parse(),再对各字段 Base64 解码为Uint8Array - 解密时传入完整 IV 和密钥对象,
crypto.subtle.decrypt()返回的 ArrayBuffer 需用TextDecoder转成字符串 - 若加密的是对象,解密后还需
JSON.parse()还原结构
必须守住的基础安全前提
再强的加密,如果运行环境不安全,就等于裸奔。
- 页面必须运行在 HTTPS 或
localhost下,HTTP 页面中crypto.subtle会静默不可用 - 启用严格的 CSP 策略,禁用
unsafe-inline和unsafe-eval,防止 XSS 窃取密钥或 hook 解密逻辑 - 避免在 HTML 中内联脚本,加密逻辑应放在独立 JS 文件中,并启用 SRI 校验
- 敏感配置项要先问自己:它真的必须存在本地吗?token、API key、密码等一律不该进 localStorage,该走
httpOnly + Secure Cookie



















