
Firefox for Android 在密码输入框中将实际密码值替换为 Unicode 圆点字符(•)并 URL 编码提交,导致后端收到的是 %E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2 而非真实密码;本文详解其成因及跨平台兼容的正确处理方式。
firefox for android 在密码输入框中将实际密码值替换为 unicode 圆点字符(•)并 url 编码提交,导致后端收到的是 `%e2%80%a2%e2%80%a2%e2%80%a2%e2%80%a2` 而非真实密码;本文详解其成因及跨平台兼容的正确处理方式。
这是一个已知的 Firefox Mobile(Android 版本 ≥120)行为:为增强前端隐私保护,浏览器在表单提交时主动将 <input type="password"> 的 value 属性值替换为 Unicode 字符 U+2022(•)并进行 URL 编码,而非提交用户实际输入的明文密码。这并非 bug,而是其安全策略的一部分——但该策略仅作用于表单直接提交(GET/POST),不影响 JavaScript 通过 element.value 获取的真实值。
因此,问题本质是:服务端接收到的不是原始密码,而是被浏览器“遮蔽化”后的编码字符串。解决的关键在于——不要依赖表单自动提交获取密码,而应通过 JavaScript 拦截提交、手动提取真实值并构造请求。
✅ 正确做法(推荐):
<form id="loginForm" action="/test">
<input id="password" type="password" name="password" placeholder="Password" autocomplete="current-password">
<button type="submit">Submit</button>
</form>
<script>
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault(); // 阻止默认提交
const passwordInput = document.getElementById('password');
const realPassword = passwordInput.value; // ✅ 此处获取的是真实输入值,不受圆点替换影响
// 构造查询参数(GET 示例)
const params = new URLSearchParams();
params.append('password', realPassword);
// 发起 fetch 请求
fetch(`/test?${params.toString()}`)
.then(res => res.text())
.then(data => console.log(data));
});
</script>⚠️ 注意事项:
- 不要使用
form.action += '?password=' + password拼接 URL,需用URLSearchParams或encodeURIComponent()确保特殊字符安全; - 若使用 POST 提交,应通过
fetch()或XMLHttpRequest发送FormData或 JSON,避免表单直提; - 后端不应直接信任或解码
•编码串(如decodeURIComponent('%E2%80%A2%E2%80%A2')),因为该值永远不是真实密码——它只是浏览器生成的占位符; - Chrome、Safari、Edge 及桌面 Firefox 均无此行为,故该问题仅出现在 Firefox for Android 当前版本中,属特定 UA 行为,无需全局降级兼容。
? 总结:Firefox Mobile 的圆点提交是前端渲染层的安全干预,不影响 DOM 中的 value 属性。开发者只需放弃传统表单直提,改用 JS 主动采集 + 显式请求,即可彻底规避此问题,并提升整体表单控制力与安全性。

















