身份证校验必须采用正则匹配与gb 11643-1999加权求和模11算法双重验证,仅用正则/^\d{17}[\dxx]$/会放行伪造号;需清洗全角、空格、短横线,校验前17位数字合法性、出生年份(1900–2099)、权重求和及校验码映射,html中应绑定blur事件并同步aria属性。

身份证号校验必须用正则 + 校验码双重验证
单纯用 /^\d{17}[\dXx]$/ 匹配 18 位数字加 X 是不够的。真实身份证最后一位是根据前 17 位算出的校验码,只校验长度和字符类型会放过大量伪造号(比如 110101199003072999 看似合法,但校验码应为 5,不是 9)。
JavaScript 中建议直接实现国标 GB 11643-1999 的加权求和模 11 算法,而不是查表或调第三方库——轻量、可控、无依赖。
- 前 17 位必须全为数字,不能含空格、短横线或中文字符
- 第 18 位允许
'0'-'9'或'X'/'x',大小写需统一转大写再比对 - 权重系数固定为
[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2],模数固定为11 - 校验码映射表为
['1','0','X','9','8','7','6','5','4','3','2']
HTML 表单中绑定实时校验的正确姿势
别在 submit 事件里才校验——用户填完一长串再提示错误体验极差。应该用 input + blur 组合,在失焦时触发,输入中可节流防抖(比如 300ms 内只校一次)。
同时要兼顾可访问性:校验失败时,aria-invalid="true" 和 aria-describedby 必须同步更新,让屏幕阅读器能读出错误提示。
- 监听
idCardInput.addEventListener('blur', validateIdCard),而非change(后者在粘贴后可能不触发) - 输入过程中可加简单格式化(如每 4 位加空格),但校验前务必先
.replace(/\s/g, '')清除所有空白符 - 避免在
input事件里高频调用校验函数,CPU 和 UX 都吃不消 - 校验通过后,记得移除
aria-invalid并清空关联的错误文案textContent
常见误判场景与绕过点
用户常手动输入带短横线的格式(如 110101-19900307-2995),或从 PDF 复制出全角数字,这些都会导致正则直接失败,但其实只是格式问题,不该算作“身份证无效”。
另外,15 位老身份证已基本停用,但部分老旧系统仍需兼容。严格来说,15 位号无校验码,只能做基础长度+数字校验,且需补零升级为 18 位后再跑完整逻辑——但这属于业务决策,不是技术必须。
- 全角数字(如 123)会被
\d忽略,要用/[\uFF10-\uFF19]/g替换为半角 - 港澳台居住证、外国人永久居留身份证等「类身份证」不适用此算法,字段名和规则完全不同
- 出生年份不能只看前 4 位是否是数字,还要检查是否在
1900–2099合理区间,否则000000000000000000也能过正则 - 地址码(前 6 位)无需联网查行政区划表,但可快速排除明显非法号段(如
000000、999999)
一个够用的 JS 校验函数示例
下面这个函数可直接塞进表单验证逻辑,返回 true 表示通过,字符串表示错误原因:
function validateIdCard(id) {
const clean = id.replace(/[\uFF10-\uFF19\s\-]/g, c => String.fromCharCode(c.charCodeAt(0) - 65248)).replace(/\s/g, '');
if (!/^\d{17}[\dXx]$/.test(clean)) return '身份证号格式错误';
const weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2];
const checkCodes = ['1','0','X','9','8','7','6','5','4','3','2'];
let sum = 0;
for (let i = 0; i 2099) return '出生年份超出合理范围';
return true;
}
注意:这个函数不处理 15 位号,也不查重、不联网验真伪。它只回答一个问题:「这个字符串,按中国第二代身份证编码规则,是否自洽?」
真正上线前,务必用公开的测试号(如官网公布的示例号)和一批已知错误号(末位错、年份错、全角错)跑一遍,漏掉任意一种都可能被用户反复投诉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











