正则匹配身份证有bug你知道么?
2019-01-16 05:49:32来源:博客园 阅读 ()
在开发中,我们需要验证用户的输入信息,多半采用正则验证,下面就是身份证证号的几种常用的正则表达式:
var reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
var reg= /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
var reg = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/;
但是这些并不能管用,是不是很气人?
这是为什么呢?
下面我们看一下身份证的规则
身份证查询系统说明:
输入准确的18位身份证号码即可查询身份证号码归属地,年龄,性别,通过身份证号码查询姓名。
输入不合法格式的身份证号码会提示身份证号码错误,本身份证号码查询系统也可作为身份证号码验证。
身份证号码和姓名格式科普:前1-6位为行政区划代码即归属地,第7-14位为出生年月日,第15-17位为顺序代码,在同一个地区出生同一个出生的人通过顺序号码区分,第17位奇数表示男性,偶数表示女性,第18位为校验码,用于校验身份证号码是否合法
很显然我们正则验证出错的原因就是第18位,用于身份证号是否合法验证的校验
这是为什么呢?是不是很诡异?按照道理讲,不应该不符合就是false?但是返回的都是true;
因为是这样的,我们使用的正则表达式 reg.test(''),当我们使用test其实就是通过我们写的正则表达式去动态匹配我们输入的字符串是否符合我们表达式的要求,如果符合就会返回Boolean值
这就是为什么我们身份证验证会出错,因为我们正则只是匹配了形式,并没有按照身份证的规则去动态验证,没有权重
那么正确的验证如下
1 /** 2 * @params idCard string 3 * @outParams res 4 * status : boolean 5 * msg : string 6 * 7 */ 8 function checkIdcard(idCard) { 9 idCard = idCard.toString(); 10 var city = { 11 11: "北京", 12 12: "天津", 13 13: "河北", 14 14: "山西", 15 15: "内蒙古", 16 21: "辽宁", 17 22: "吉林", 18 23: "黑龙江 ", 19 31: "上海", 20 32: "江苏", 21 33: "浙江", 22 34: "安徽", 23 35: "福建", 24 36: "江西", 25 37: "山东", 26 41: "河南", 27 42: "湖北 ", 28 43: "湖南", 29 44: "广东", 30 45: "广西", 31 46: "海南", 32 50: "重庆", 33 51: "四川", 34 52: "贵州", 35 53: "云南", 36 54: "西藏 ", 37 61: "陕西", 38 62: "甘肃", 39 63: "青海", 40 64: "宁夏", 41 65: "新疆", 42 71: "台湾", 43 81: "香港", 44 82: "澳门", 45 91: "国外 " 46 }; 47 var tip = ""; 48 var pass = true; 49 50 if ( 51 !idCard || 52 !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test( 53 idCard 54 ) 55 ) { 56 tip = "身份证号格式错误"; 57 pass = false; 58 } else if (!city[idCard.substr(0, 2)]) { 59 tip = "地址编码错误"; 60 pass = false; 61 } else { 62 //18位身份证需要验证最后一位校验位 63 if (idCard.length == 18) { 64 idCard = idCard.split(""); 65 //∑(ai×Wi)(mod 11) 66 //加权因子 67 var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; 68 //校验位 69 var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2]; 70 var sum = 0; 71 var ai = 0; 72 var wi = 0; 73 for (var i = 0; i < 17; i++) { 74 ai = idCard[i]; 75 wi = factor[i]; 76 sum += ai * wi; 77 } 78 var last = parity[sum % 11]; 79 if (parity[sum % 11] != idCard[17]) { 80 tip = "校验位错误"; 81 pass = false; 82 } 83 } 84 } 85 var obj = { 86 status: pass, 87 msg: tip 88 }; 89 if (!pass) { 90 return obj; 91 } 92 93 return obj; 94 }
写法注意事项:省区编码,我们可以写成数组的形式,但是需要去循环操作,会比较消耗性能:如果是数组,新手是这么写的
function checkIdcard(idCard) { idCard = idCard.toString(); var city = [ 11, 12, 13, 14, 15, 21, 22, 23, 31, 33, 34, 35, 36, 37, 41, 42, 43, 44, 45, 46, 50, 51, 52, 54, 61, 62, 63, 64, 65, 71, 81, 91 ]; var tip = ""; var pass = true; var Flag = true; for(var i=0;i<city.length;i++){ if (city[i] == idCard.substr(0, 2)) Falg= false; } if ( !idCard || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test( idCard ) ) { tip = "身份证号格式错误"; pass = false; } else if (!Flag) { tip = "地址编码错误"; pass = false; } else { //18位身份证需要验证最后一位校验位 if (idCard.length == 18) { idCard = idCard.split(""); //∑(ai×Wi)(mod 11) //加权因子 var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; //校验位 var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2]; var sum = 0; var ai = 0; var wi = 0; for (var i = 0; i < 17; i++) { ai = idCard[i]; wi = factor[i]; sum += ai * wi; } var last = parity[sum % 11]; if (parity[sum % 11] != idCard[17]) { tip = "校验位错误"; pass = false; } } } var obj = { status: pass, msg: tip }; if (!pass) { return obj; } return obj; }
优化上面的代码
/** * @params idCard string * @outParams res * status : boolean * msg : string * */ function checkIdcard(idCard) { idCard = idCard.toString(); var city = [ 11, 12, 13, 14, 15, 21, 22, 23, 31, 33, 34, 35, 36, 37, 41, 42, 43, 44, 45, 46, 50, 51, 52, 54, 61, 62, 63, 64, 65, 71, 81, 91 ]; var tip = ""; var pass = true; if ( !idCard || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test( idCard ) ) { tip = "身份证号格式错误"; pass = false; } else if (city.indexOf(idCard.substr(0, 2)) < 0) { tip = "地址编码错误"; pass = false; } else { //18位身份证需要验证最后一位校验位 if (idCard.length == 18) { idCard = idCard.split(""); //∑(ai×Wi)(mod 11) //加权因子 var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; //校验位 var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2]; var sum = 0; var ai = 0; var wi = 0; for (var i = 0; i < 17; i++) { ai = idCard[i]; wi = factor[i]; sum += ai * wi; } var last = parity[sum % 11]; if (parity[sum % 11] != idCard[17]) { tip = "校验位错误"; pass = false; } } } var obj = { status: pass, msg: tip }; if (!pass) { return obj; } return obj; }
注意一下写法,尽量减少循环的操作,推荐使用第一种和第三种用法;如果你是es6用户,那么建议var 修改成 let
最后基于模块的思想,建议搭建可以在实际开发中,把验证的方法统一一个对象去处理,
然后哪里需要哪里引入。
参考博文:https://blog.csdn.net/a632202838/article/details/44827427
在线身份查询:http://sfz.diqibu.com/
原文链接:https://www.cnblogs.com/starryqian/p/10272793.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:14JavaScript条件语句
下一篇:分享js获取变量的代码
- jquery基本选择器匹配多个元素的实现方法 2019-09-08
- Javascript正则 2019-08-14
- 常用正则表达式 2019-08-14
- JavaScript RegExp(正则表达式) 对象 2019-08-14
- 手机号码正则表达式 2019-08-14
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash