先记住这个答案
隐藏输入常用于把记录 ID、来源页面或一次操作的上下文带到服务端。它与普通具名输入一样可以提交 name=value,只是用户界面不显示。浏览器开发工具、脚本乃至手写请求都能改这个值,因此隐藏不是加密,更不是授权凭据。服务器要重新确认当前用户能否操作该 ID。
- 隐藏不等于保密或不可修改
- 具名启用字段会提交
value - 适合携带上下文或记录标识
- 服务器必须校验权限和真实性
记录 ID 为什么能随表单走
编辑资料表单往往需要告诉服务器正在修改哪条记录。放一个 name="recordId" 的隐藏字段,表单提交时就能带上这个 ID;name 缺失则通常不会形成表单数据项,disabled 也会阻止它进入结果。
<form action="/records/update" method="post">
<input type="hidden" name="recordId" value="42">
<label for="title">标题</label>
<input id="title" name="title">
<button type="submit">保存</button>
</form>服务器收到 recordId=42 后,还要验证当前登录用户有权修改 42 号记录。用户完全可能把值改成 43;仅凭隐藏字段就更新数据库会造成越权。
它适合传上下文,不适合传信任
隐藏字段可以承载筛选返回地址、当前步骤编号或一次提交需要的普通上下文。价格、折扣、角色、权限这些会影响安全或金额的值,不应因藏在 HTML 里就被服务器信任。需要防重放或跨站请求保护时,应使用服务端认可的机制,并正确验证,而不是自定义一个不校验的隐藏令牌。
type="hidden" 不给用户一个可见编辑界面,也不参与通常的约束校验;这不是“值一定正确”的保证。客户端输入都应按接口契约处理,隐藏与可见只是 UI 差异。删除操作同样不能只信任这个 ID。
例如编辑订单时提交 <input type="hidden" name="orderId" value="123">,服务端可据此知道用户想编辑哪一条,但绝不能因此认定这个用户有权编辑 123。隐藏控件只是没有可见界面的普通表单字段,开发者工具里可直接改值,抓包也能重放。服务端应按当前登录身份重新查订单并做权限判断。需要防跨站请求伪造时,可以放有服务端校验机制的令牌;令牌有效性来自服务器验证,不来自 hidden 这个类型本身。
容易答错的地方
- 把隐藏字段当成安全存储
- 网页源码和请求体都能看到它,用户可修改;密钥不能放进去。
- 认为没有
name也会提交 - 普通表单数据以字段名和值组成,缺少
name通常不会产生对应项。
面试官还会怎么问?
隐藏字段被禁用后还会提交吗?
不会。disabled 控件不属于普通提交的成功控件。
能用隐藏字段传 CSRF token 吗?
可以作为载体之一,但服务端必须按会话等规则验证 token,隐藏本身不提供保护。
怎样防止用户改记录 ID?
无法阻止客户端修改;服务器应根据身份检查目标记录的授权。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。