不能在本地加密存储表单敏感数据,因为密钥必然暴露于前端可控环境,localstorage 无隔离机制,加密形同虚设;仅可安全暂存脱敏的非pii草稿数据。

不能在本地加密存储表单提交数据——这不是功能缺失,而是安全设计的主动放弃。浏览器环境里,任何“前端加密后存 localStorage”的做法,等价于把密钥和保险箱一起放在门口。
为什么 crypto.subtle.encrypt + localStorage 是危险组合
你写了一段用 crypto.subtle.encrypt() 加密密码再塞进 localStorage 的代码,看起来很专业。但问题在于:
- 密钥(
key)必须由 JS 生成或从服务端获取,而 JS 运行在用户可控环境,攻击者可直接 console.log 或断点提取密钥 -
localStorage本身无访问隔离,同源下任意脚本(包括被 XSS 注入的)都能读取、篡改、删除内容 - 加密后的数据一旦落盘,就脱离了运行时保护,变成静态密文+明文密钥的裸奔状态
- 现代浏览器对
localStorage的容量限制(通常 5–10MB)、无过期机制、无法加密存储,进一步放大风险
真正该存本地的,只有非敏感中间态数据
表单填写过程中的草稿、未提交的结构化字段值、用户偏好设置——这些可以且应该本地暂存,但必须满足两个前提:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 字段不含密码、身份证号、银行卡号、手机号等 PII(个人身份信息)
- 存之前做基础清洗:移除
undefined、function、DOM 节点;用JSON.stringify()序列化;还原时用try...catch包住JSON.parse() - 键名带上下文:比如
localStorage.setItem(`${location.pathname}_${form.id}_draft`, dataStr),避免跨表单污染 - 加防抖(debounce):监听
input时用setTimeout延迟 300ms 再存,避开中文输入法选词过程中的脏触发
敏感字段连“暂存”都该禁止
如果表单含密码或证件号,连“用户填一半关了页面再回来继续”的需求,都不该用本地存储实现:
- 密码字段应始终用
type="password",配合autocomplete="new-password"防止浏览器自动填充旧值 - 身份证/银行卡号字段建议加
inputmode="numeric"+pattern="[0-9]{17}[0-9Xx]?",但绝不存本地 - 真有合规要求(如金融内网离线录入),必须用
IndexedDB配合 Service Worker 加密封装,且密钥由设备级可信执行环境(TEE)或服务端动态派生,不落地 - localStorage 存敏感字段,等于把钥匙交给每个路过的人——哪怕你加了 AES-GCM,也改变不了密钥暴露的事实
最容易被忽略的点:不是“能不能加密”,而是“有没有必要加密”。表单数据的本地存储目标从来不是保密,而是防丢。只要字段本身不敏感,存明文 JSON 就是合理选择;一旦涉及敏感字段,第一反应不应该是“怎么加密存”,而是“能不能不存”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










