经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 其他 » 正则表达式 » 查看文章
正则匹配身份证有bug你知道么?
来源:cnblogs  作者:星光笔  时间:2019/1/16 9:18:56  对本文有异议

在开发中,我们需要验证用户的输入信息,多半采用正则验证,下面就是身份证证号的几种常用的正则表达式:

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.  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       idCard54     )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       //&sum;(ai&times;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: tip88   };89   if (!pass) {90     return obj;91   }92 93   return obj;94 }

写法注意事项:省区编码,我们可以写成数组的形式,但是需要去循环操作,会比较消耗性能:如果是数组,新手是这么写的

  1. function checkIdcard(idCard) {
  2.   idCard = idCard.toString();
  3.   var city = [
  4.     11,
  5.     12,
  6.     13,
  7.     14,
  8.     15,
  9.     21,
  10.     22,
  11.     23,
  12.     31,
  13.     33,
  14.     34,
  15.     35,
  16.     36,
  17.     37,
  18.     41,
  19.     42,
  20.     43,
  21.     44,
  22.     45,
  23.     46,
  24.     50,
  25.     51,
  26.     52,
  27.     54,
  28.     61,
  29.     62,
  30.     63,
  31.     64,
  32.     65,
  33.     71,
  34.     81,
  35.     91
  36.   ];
  37.   var tip = "";
  38.   var pass = true;
  39.   var Flag = true;
  40.   for(var i=0;i<city.length;i++){
  41.     if (city[i] == idCard.substr(0, 2)) Falg= false;
  42.   }
  43.   if (
  44.     !idCard ||
  45.     !/^\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(
  46.       idCard
  47.     )
  48.   ) {
  49.     tip = "身份证号格式错误";
  50.     pass = false;
  51.   } else if (!Flag) {
  52.            tip = "地址编码错误";
  53.            pass = false;
  54.          } else {
  55.            //18位身份证需要验证最后一位校验位
  56.            if (idCard.length == 18) {
  57.              idCard = idCard.split("");
  58.              //&sum;(ai&times;Wi)(mod 11)
  59.              //加权因子
  60.              var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  61.              //校验位
  62.              var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2];
  63.              var sum = 0;
  64.              var ai = 0;
  65.              var wi = 0;
  66.              for (var i = 0; i < 17; i++) {
  67.                ai = idCard[i];
  68.                wi = factor[i];
  69.                sum += ai * wi;
  70.              }
  71.              var last = parity[sum % 11];
  72.              if (parity[sum % 11] != idCard[17]) {
  73.                tip = "校验位错误";
  74.                pass = false;
  75.              }
  76.            }
  77.          }
  78.   var obj = {
  79.     status: pass,
  80.     msg: tip
  81.   };
  82.   if (!pass) {
  83.     return obj;
  84.   }
  85.  
  86.   return obj;
  87. }

  优化上面的代码

  1. /**
  2.  * @params  idCard  string
  3.  * @outParams res
  4.  *  status : boolean
  5.  *  msg : string
  6.  * */function checkIdcard(idCard) {
  7.   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
  8.   ];  var tip = "";  var pass = true;  if (!idCard ||
  9.     !/^\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(
  10.       idCard
  11.     )
  12.   ) {
  13.     tip = "身份证号格式错误";
  14.     pass = false;
  15.   } else if (city.indexOf(idCard.substr(0, 2)) < 0) {
  16.     tip = "地址编码错误";
  17.     pass = false;
  18.   } else {//18位身份证需要验证最后一位校验位if (idCard.length == 18) {
  19.       idCard = idCard.split("");      //&sum;(ai&times;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++) {
  20.         ai = idCard[i];
  21.         wi = factor[i];
  22.         sum += ai * wi;
  23.       }      var last = parity[sum % 11];      if (parity[sum % 11] != idCard[17]) {
  24.         tip = "校验位错误";
  25.         pass = false;
  26.       }
  27.     }
  28.   }  var obj = {
  29.     status: pass,
  30.     msg: tip
  31.   };  if (!pass) {return obj;
  32.   }  return obj;
  33. }

注意一下写法,尽量减少循环的操作,推荐使用第一种和第三种用法;如果你是es6用户,那么建议var 修改成 let 

最后基于模块的思想,建议搭建可以在实际开发中,把验证的方法统一一个对象去处理,

然后哪里需要哪里引入。

参考博文:https://blog.csdn.net/a632202838/article/details/44827427

在线身份查询:http://sfz.diqibu.com/

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号