hidden input 本质是传递服务端可控、可验证的上下文,须满足后端生成、有明确范围、可二次核验三条件;禁放金额、权限、密钥类敏感信息;name、type、form 包裹及 js 更新时机均需规范。

在 H5 页面中用 <input type="hidden"> 传业务参数,本质不是“藏数据”,而是把服务端已确认、用户不该改、也不该看的上下文稳稳带上——安全的关键不在前端怎么写,而在后端是否校验、字段是否选对、逻辑是否隔离。
只传服务端可控、可验证的上下文
适合放进 hidden 字段的值,必须满足三个条件:由后端生成或签发、有明确取值范围、提交后能被二次核验。比如:
- 订单 ID(
orderId):从后端接口返回,数据库主键,非用户输入 - 渠道标识(
paymentChannel):如"alipay"、"wechat",仅限预设枚举值 - 防重放时间戳 + nonce(
timestamp和nonce):组合签名,后端验证是否过期、是否重复 - CSRF token(
csrf_token):与当前 session 绑定,一次一换,后端比对失效即拒 - 页面来源标记(
ref或origin):用于日志归因,不参与权限或金额判断
绝对不能放的三类敏感信息
这些字段哪怕加了 type="hidden",也等于贴在网页源码上供人修改:
-
金额相关:如
amount、discount、total_price—— 后端必须从订单库查,客户端值仅作展示比对 -
权限与身份标识:如
role="admin"、is_vip="1"、user_id="999999"—— 角色和权限必须由后端 session 或 token 解析决定 -
密钥与凭证:如
api_key、access_token、bank_card_no—— 这些本就不该出现在前端,更不该塞进表单
写法必须规范,否则后端根本收不到
很多“传不上去”的问题,其实不是安全问题,而是基础错误:
-
name 属性不可省略:没有
name,浏览器不提交;拼错大小写(如userIdvsuser_id)会导致后端取不到 -
type 必须小写且准确:写成
type="HIDDEN"或type="hide",部分浏览器会降级为文本框,可能意外暴露 - 必须放在 :游离在 form 外的 hidden input 不参与提交
-
避免 disabled:加了
disabled的字段即使隐藏也不会提交
JS 动态更新要卡准时机,别让旧值溜走
支付页切换渠道、多步骤表单跳转等场景,需要 JS 实时改 value,但常见失误是:
- 脚本放在
里就执行,DOM 还没加载,getElementById返回null - 监听
click而非change,移动端可能不触发;或只监听一次,没覆盖后续选择 - 在
submit事件末尾才赋值,用户连点两次,第二次提交仍是旧值
正确做法:绑定到 form.onsubmit 开头,或在选项确定后立即同步,例如:
document.getElementById('payMethod').value = selectedChannel;











