html本身不支持加密,所谓“html加密”是误称;真正可行的是在html表格中做数据脱敏,且必须配合服务端或客户端逻辑完成。

HTML 本身不支持加密,所谓“HTML 加密”是误称;真正可行的是在 HTML 表格中做数据脱敏,且必须配合服务端或客户端逻辑完成。
为什么不能在 HTML 中直接加密数据
HTML 是纯标记语言,没有执行能力,localStorage、innerHTML、textContent 等操作都不具备加解密能力。试图用 base64 编码 <td>base64encode("138****1234")</td> 并不是加密,只是编码,可被任意工具秒级还原。浏览器里跑 JavaScript 解密,密钥若硬编码在前端,等于把锁和钥匙一起贴在门上。
常见错误现象:
- 用
btoa()/atob()处理手机号,被用户打开控制台一查就暴露原始值 - 把 AES 密钥写死在 JS 文件里,打包后仍可被静态提取
- 以为给
<table> 加个 <code>encrypted自定义属性就算“加密”了HTML 表格中做数据脱敏的三种可靠方式
脱敏目标是让敏感字段(如
idCard、phone、email)在页面上不可逆地变形,且不依赖密钥管理。实际落地分三类:-
服务端模板层脱敏:后端渲染时直接处理,例如 Spring Boot 的
@JsonSerialize(using = PhoneMaskSerializer.class),返回的 JSON 中phone字段已是"138****1234" -
前端 JS 脱敏(推荐轻量场景):用正则或
substring()实时处理,例如phone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");注意必须在render或innerHTML插入前执行,不能等 DOM 渲染完再遍历querySelectorAll("td.phone")—— 那会短暂闪现明文 -
CSS 层遮蔽(仅视觉,不防审查):用
text-security: disc;或伪元素 +clip-path遮挡部分内容,但右键“检查元素”仍可见原始 HTML,仅适合内部低敏系统快速上线
动态脱敏 vs 静态脱敏在表格中的取舍
关键看数据来源和权限粒度:
- 如果所有用户看到的表格数据都一样(如公开报表),用 静态脱敏:数据库查询时就用
CONCAT(LEFT(phone,3), '****', RIGHT(phone,4))或 MyBatis 的<bind></bind>标签预处理 - 如果不同角色看到不同精度(如客服能看到完整手机号,实习生只能看前3后4),必须走 动态脱敏:请求带
role=intern,后端根据上下文决定是否调用maskPhone(),再塞进表格 JSON - 避免在前端用
if (user.role === 'admin') { showRaw() } else { mask() }—— role 可被篡改,脱敏逻辑必须由可信服务端控制
容易被忽略的兼容性与安全细节
脱敏不是加几颗星号就完事。真实项目里常踩的坑包括:
- 国际化场景下,
substring(0,3)对中文姓名或日文片假名会截断字节,应改用.slice(0,3)或正则/^[\u4e00-\u9fa5a-zA-Z0-9]{1,3}/ - 表格导出 Excel(如用
SheetJS)时,若只脱敏了 DOM,导出内容仍是明文 —— 必须在生成worksheet前对数据源做二次脱敏 - 使用
contenteditable表格时,用户可能手动删掉****,需监听input事件并强制重置格式 - 搜索功能若基于原始数据过滤,脱敏后的显示值和搜索值不一致,得在服务端统一用脱敏后字段建索引,或前端搜索前先对 keyword 做同规则变形
最复杂的点往往不在“怎么遮”,而在于“在哪一刻遮”——是在数据库 SELECT 时、API 序列化时、还是 React
useMemo计算时?选错时机,脱敏就形同虚设。 -
服务端模板层脱敏:后端渲染时直接处理,例如 Spring Boot 的
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











