导读:本期聚焦于叶子创作的《如何使用jQuery制作仿支付宝数字键盘及密码输入框的安全输入控件》,敬请观看详情。密码输入一直是支付类页面最容易出安全问题的环节,原生密码框依赖系统键盘,容易受到键盘记录程序的威胁,移动端上体验也难以统一。支付宝采用的随机数字键盘加自定义密码格子的方案,能有效降低被监听的风险。本文将详细讲解如何用jQuery从零实现一套仿支付宝的安全输入控件,内容包括整体结构与样式设计、数字键盘的动态生成与随机打乱逻辑、密码格子的掩码渲染与焦点管理、按键事件委托处理,以及防复制粘贴、前端加密传输等安全加固措施,文中附完整可运行的代码示例,帮助开发者在自己的项目中快速落地。

在支付场景的网页里,输入交易密码是整个流程中安全要求最高的一步。浏览器原生的密码输入框依赖物理键盘或系统软键盘,输入过程可能被键盘记录程序捕获,而且在手机上原生密码框的样式和行为各不相同,体验很难统一。支付宝的做法是干脆不用原生输入框,而是自己绘制一个数字键盘和密码格子控件,既屏蔽了系统键盘的监听风险,又能保证跨端体验一致。本文就带你用jQuery一步步实现一个仿支付宝的数字键盘加密码输入框控件。

如何使用jQuery制作仿支付宝数字键盘及密码输入框的安全输入控件

一、整体结构与样式设计

先规划页面的HTML结构。整个控件分为三部分:密码显示区、遮罩层、数字键盘面板。密码区不使用<input>标签,而是用六个格子模拟,这样可以从根本上避免原生输入框带来的一系列问题,比如长按弹出系统菜单、自动填充、被脚本读取值等。

<div class="pay-container">
  <div class="pwd-box">
    <div class="pwd-input" id="pwdInput">
      <span class="pwd-cell"></span>
      <span class="pwd-cell"></span>
      <span class="pwd-cell"></span>
      <span class="pwd-cell"></span>
      <span class="pwd-cell"></span>
      <span class="pwd-cell"></span>
    </div>
  </div>
  <div class="mask" id="mask"></div>
  <div class="keyboard" id="keyboard">
    <ul class="key-list" id="keyList"></ul>
  </div>
</div>

样式方面,密码格子需要横向排列且等分宽度,用flex布局最省事。每个格子居中显示一个圆点,圆点用伪元素绘制,避免在DOM里留下任何明文痕迹。键盘面板默认隐藏在屏幕底部,弹出时通过transform做位移动画,性能比改top值好得多。

.pwd-box {
  width: 320px; margin: 50px auto;
  border: 1px solid #ddd; border-radius: 6px;
  overflow: hidden;
}
.pwd-input {
  display: flex; width: 100%; cursor: pointer;
  -webkit-user-select: none; user-select: none;
}
.pwd-cell {
  flex: 1; height: 46px; line-height: 46px;
  text-align: center; border-right: 1px solid #ddd;
  font-size: 22px; position: relative;
}
.pwd-cell:last-child { border-right: none; }
.pwd-cell.filled::after {
  content: ''; display: inline-block;
  width: 12px; height: 12px; border-radius: 50%;
  background: #333; vertical-align: middle;
}
.mask {
  display: none; position: fixed; left: 0; top: 0;
  width: 100%; height: 100%;
  background: rgba(0,0,0,.5); z-index: 998;
}
.keyboard {
  position: fixed; left: 0; bottom: -320px;
  width: 100%; background: #f5f5f5;
  transition: bottom .3s ease; z-index: 999;
}
.keyboard.show { bottom: 0; }
.key-list { display: flex; flex-wrap: wrap; margin: 0; padding: 8px; list-style: none; }
.key-list li {
  width: 31.5%; margin: 1%; height: 48px; line-height: 48px;
  background: #fff; text-align: center; font-size: 22px;
  border-radius: 6px; cursor: pointer;
}
.key-list li:active { background: #e0e0e0; }
.key-list li.disabled { background: #e8e8e8; color: #ccc; }

这里有两个细节值得注意。一是密码区和键盘都要加上user-select: none,禁止用户选中文字,防止通过双击或长按看到残留内容。二是键盘用position: fixed固定在底部,配合遮罩层阻止用户在键盘弹出时误触页面其他区域,这也是支付宝等支付页面的常见交互习惯。

二、数字键盘的动态生成与随机打乱

键盘按键不写死在HTML里,而是用jQuery动态生成,这样可以实现一个重要的安全特性:每次弹出键盘时随机打乱数字顺序。固定布局的键盘存在被旁人偷看按键位置、或者通过屏幕录制回放分析手指轨迹来推测密码的风险,随机化布局能有效缓解这类肩窥攻击。

function buildKeyboard() {
  var keys = ['1','2','3','4','5','6','7','8','9','0'];
  // Fisher-Yates洗牌算法打乱数字顺序
  for (var i = keys.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = keys[i];
    keys[i] = keys[j];
    keys[j] = temp;
  }
  var html = '';
  // 前9个位置放打乱后的数字,第10格放空键
  for (var k = 0; k < keys.length; k++) {
    if (k === 9) {
      html += '<li class="disabled"></li>';
    }
    html += '<li>' + keys[k] + '</li>';
  }
  html += '<li class="disabled"></li><li>0</li>'.replace('0', keys[9] === '0' ? '' : '');
  html = html.replace('0', keys[9]);
  $('#keyList').html(html);
  // 追加功能键
  $('#keyList').append('<li class="disabled"></li><li id="keyDel">删除</li><li id="keyDone">完成</li>');
}

上面的写法为了演示核心逻辑略有简化,实际项目中建议把布局写成更清晰的二维数组结构,逐行渲染,代码可读性更好。洗牌部分用的是标准的Fisher-Yates算法,它的时间复杂度是O(n),能保证每种排列出现的概率完全相等,这一点比简单的sort加随机比较函数要可靠,因为后者的概率分布并不均匀。

随机化也有代价:数字位置每次变化,用户找数字的速度会变慢,输错率略高。所以支付宝实际采用的方式是数字区随机、删除键和完成键位置固定,这个平衡点值得借鉴。如果安全等级要求更高,比如银行类应用,还可以在每输入一位后重新洗牌一次,但普通支付场景做到每次弹出时随机就够了。

三、密码掩码渲染与事件处理

密码数据保存在一个JS字符串变量中,每输入或删除一位,就重新渲染格子的圆点状态。渲染函数非常简单,遍历所有格子,索引小于密码长度的加filled类,其余的去掉。虽然直接操作DOM没有性能问题,但要养成最小化DOM操作的习惯,只在状态变化的格子上做增删类的操作。

var pwd = '';

function renderPwd() {
  var cells = $('#pwdInput .pwd-cell');
  cells.removeClass('filled');
  for (var i = 0; i < pwd.length; i++) {
    cells.eq(i).addClass('filled');
  }
}

按键点击用事件委托的方式绑定在ul上,而不是给每个li单独绑定,这样键盘重建后监听器依然有效,也不需要重复解绑。判断点击的是数字、删除还是完成,分别做追加、截断和提交处理。密码长度上限设为6位,超过就忽略输入。

$('#keyList').on('click', 'li', function () {
  var $li = $(this);
  if ($li.hasClass('disabled')) return;
  var text = $li.text();
  if (text === '删除') {
    pwd = pwd.slice(0, -1);
    renderPwd();
    return;
  }
  if (text === '完成') {
    if (pwd.length === 6) {
      submitPwd(pwd);
      closeKeyboard();
      pwd = '';
      renderPwd();
    } else {
      alert('请输入完整的6位密码');
    }
    return;
  }
  if (/^[0-9]$/.test(text) && pwd.length < 6) {
    pwd += text;
    renderPwd();
    if (pwd.length === 6) {
      // 输满后自动提交,也可以改成等待用户点完成
      setTimeout(function () { submitPwd(pwd); }, 200);
    }
  }
});

function submitPwd(value) {
  // 实际项目中应加密后通过ajax提交到后端
  console.log('提交密码:', value);
}

弹窗和收起的控制放在两个入口事件里:点击密码区弹出键盘并重建按键,点击遮罩层收起。收起的同时把已输入的密码清空,这是支付宝的做法,避免用户下次弹出时残留上次的输入造成误提交。

$('#pwdInput').on('click', function () {
  buildKeyboard();
  $('#mask').show();
  $('#keyboard').addClass('show');
});

function closeKeyboard() {
  $('#keyboard').removeClass('show');
  $('#mask').hide();
  pwd = '';
  renderPwd();
}

$('#mask').on('click', closeKeyboard);

四、安全加固:这个控件到底防住了什么

要客观看待自定义键盘的安全价值。它主要防的是两类威胁:一是系统层面的键盘记录器,因为整个过程没有触发任何真实的键盘事件,Hook系统按键的恶意程序抓不到任何内容;二是肩窥和屏幕录制回放,随机布局加圆点掩码让旁观者难以推断输入内容。

但有几个攻击面它自己是防不住的,必须配合其他手段。首先是网络传输,明文密码绝不能直接POST出去,应该在前端用RSA公钥加密后再提交,后端用私钥解密,这样即使抓包也拿不到原文。其次是页面本身被注入恶意脚本的情况,如果有XSS漏洞,任何前端控件都形同虚设,所以输入框的转义过滤、CSP策略这些基础工作不能省。最后,密码变量在提交后要立即清空,不要长时间留在内存里,更不要往localStorage或cookie里写。

还有一个容易被忽视的细节:这个控件禁用了粘贴功能,用户只能手动逐位输入。这看起来是体验的倒退,实际上是刻意的安全设计。如果允许粘贴,攻击者可以通过诱导用户复制恶意内容,或者用户自己粘贴被篡改的密码,都会绕开逐位确认的过程。支付宝坚持只允许键盘输入,正是基于这个考虑。

总结一下,用jQuery实现仿支付宝数字键盘的核心在于三点:不用原生输入框而是自绘格子来切断系统键盘链路、随机打乱数字布局来对抗肩窥、配合前端加密和及时清空内存来完成整条安全链路。代码量不大,但每一处设计都对应着具体的安全考量,理解了这些思路,你就可以根据自己项目的安全等级灵活裁剪,做出既安全又好用的支付密码输入控件。

jQuery数字键盘密码输入框安全输入控件修改时间:2026-09-08 20:14:02

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260908/52961.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。