博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Js实现中国公民身份证号码有效性验证
阅读量:5878 次
发布时间:2019-06-19

本文共 8323 字,大约阅读时间需要 27 分钟。

hot3.png

 

参考:

本文将使用JavaScript实现中国公民(15位或者18位)身份证号码的相关验证,功能如下:

  • 身份证号有效性验证
  • 分析详细身份证信息
  • 生成一个虚拟的省份证号码。

 

身份证号码验证

  1. 号码的结构 公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
  2. 地址码(前六位数)
    表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
  3. 出生日期码(第七位至十四位)
    表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
  4. 顺序码(第十五位至十七位)
    表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号, 顺序码的奇数分配给男性,偶数分配给女性。
  5. 校验码(第十八位数)
    (1)十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0, … , 16 ,先对前17位数字的权求和
    Ai:表示第i位置上的身份证号码数字值
    Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
    (2)计算模 Y = mod(S, 11)
    (3)通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9 8 7 6 5 4 3 2

此处将使用一个全国的地址码 GB2260,在下面的下载地址可以看到。

function IDValidator() {	var param = {		error : {			longNumber : '长数字存在精度问题,请使用字符串传值! Long number is not allowed, because the precision of the Number In JavaScript.'		}	};	var util = {		checkArg : function(id) {			var argType = (typeof id);			switch (argType) {			case 'number':				// long number not allowed				id = id.toString();				if (id.length > 15) {					this.error(param.error.longNumber);					return false;				}				break;			case 'string':				break;			default:				return false;			}			id = id.toUpperCase();			var code = null;			if (id.length === 18) {				// 18位				code = {					body : id.slice(0, 17),					checkBit : id.slice(-1),					type : 18				};			} else if (id.length === 15) {				// 15位				code = {					body : id,					type : 15				};			} else {				return false;			}			return code;		}		// 地址码检查		,		checkAddr : function(addr, GB2260) {			var addrInfo = this.getAddrInfo(addr, GB2260);			return (addrInfo === false ? false : true);		}		// 取得地址码信息		,		getAddrInfo : function(addr, GB2260) {			GB2260 = GB2260 || null;			// 查询GB/T2260,没有引入GB2260时略过			if (GB2260 === null) {				return addr;			}			if (!GB2260.hasOwnProperty(addr)) {				// 考虑标准不全的情况,搜索不到时向上搜索				var tmpAddr;				tmpAddr = addr.slice(0, 4) + '00';				if (!GB2260.hasOwnProperty(tmpAddr)) {					tmpAddr = addr.slice(0, 2) + '0000';					if (!GB2260.hasOwnProperty(tmpAddr)) {						return false;					} else {						return GB2260[tmpAddr] + '未知地区';					}				} else {					return GB2260[tmpAddr] + '未知地区';				}			} else {				return GB2260[addr];			}		}		// 生日码检查		,		checkBirth : function(birth) {			var year, month, day;			if (birth.length == 8) {				year = parseInt(birth.slice(0, 4), 10);				month = parseInt(birth.slice(4, 6), 10);				day = parseInt(birth.slice(-2), 10);			} else if (birth.length == 6) {				year = parseInt('19' + birth.slice(0, 2), 10);				month = parseInt(birth.slice(2, 4), 10);				day = parseInt(birth.slice(-2), 10);			} else {				return false;			}			// TODO 是否需要判断年份			/*			 * if( year<1800 ){ return false; }			 */			// TODO 按月份检测			if (month > 12 || month === 0 || day > 31 || day === 0) {				return false;			}			return true;		}		// 顺序码检查		,		checkOrder : function(order) {			// 暂无需检测			return true;		}		// 加权		,		weight : function(t) {			return Math.pow(2, t - 1) % 11;		}		// 随机整数		,		rand : function(max, min) {			min = min || 1;			return Math.round(Math.random() * (max - min)) + min;		}		// 数字补位		,		str_pad : function(str, len, chr, right) {			str = str.toString();			len = len || 2;			chr = chr || '0';			right = right || false;			if (str.length >= len) {				return str;			} else {				for (var i = 0, j = len - str.length; i < j; i++) {					if (right) {						str = str + chr;					} else {						str = chr + str;					}				}				return str;			}		}		// 抛错		,		error : function(msg) {			var e = new Error();			e.message = 'IDValidator: ' + msg;			throw e;		}	};	var _IDValidator = function(GB2260) {		if (typeof GB2260 !== "undefined") {			this.GB2260 = GB2260;		}		// 建立cache		this.cache = {};	};	_IDValidator.prototype = {		isValid : function(id) {			var GB2260 = this.GB2260 || null;			var code = util.checkArg(id);			if (code === false) {				return false;			}			// 查询cache			if (this.cache.hasOwnProperty(id)					&& typeof this.cache[id].valid !== 'undefined') {				return this.cache[id].valid;			} else {				if (!this.cache.hasOwnProperty(id)) {					this.cache[id] = {};				}			}			var addr = code.body.slice(0, 6);			var birth = (code.type === 18 ? code.body.slice(6, 14) : code.body					.slice(6, 12));			var order = code.body.slice(-3);			if (!(util.checkAddr(addr, GB2260) && util.checkBirth(birth) && util					.checkOrder(order))) {				this.cache[id].valid = false;				return false;			}			// 15位不含校验码,到此已结束			if (code.type === 15) {				this.cache[id].valid = true;				return true;			}			/* 校验位部分 */			// 位置加权			var posWeight = [];			for (var i = 18; i > 1; i--) {				var wei = util.weight(i);				posWeight[i] = wei;			}			// 累加body部分与位置加权的积			var bodySum = 0;			var bodyArr = code.body.split('');			for (var j = 0; j < bodyArr.length; j++) {				bodySum += (parseInt(bodyArr[j], 10) * posWeight[18 - j]);			}			// 得出校验码			var checkBit = 12 - (bodySum % 11);			if (checkBit == 10) {				checkBit = 'X';			} else if (checkBit > 10) {				checkBit = checkBit % 11;			}			checkBit = (typeof checkBit === 'number' ? checkBit.toString()					: checkBit);			// 检查校验码			if (checkBit !== code.checkBit) {				this.cache[id].valid = false;				return false;			} else {				this.cache[id].valid = true;				return true;			}		}		// 分析详细信息		,		getInfo : function(id) {			var GB2260 = this.GB2260 || null;			// 号码必须有效			if (this.isValid(id) === false) {				return false;			}			// TODO 复用此部分			var code = util.checkArg(id);			// 查询cache			// 到此时通过isValid已经有了cache记录			if (typeof this.cache[id].info !== 'undefined') {				return this.cache[id].info;			}			var addr = code.body.slice(0, 6);			var birth = (code.type === 18 ? code.body.slice(6, 14) : code.body					.slice(6, 12));			var order = code.body.slice(-3);			var info = {};			info.addrCode = addr;			if (GB2260 !== null) {				info.addr = util.getAddrInfo(addr, GB2260);			}			info.birth = (code.type === 18 ? (([ birth.slice(0, 4),					birth.slice(4, 6), birth.slice(-2) ]).join('-')) : ([					'19' + birth.slice(0, 2), birth.slice(2, 4),					birth.slice(-2) ]).join('-'));			info.sex = (order % 2 === 0 ? 0 : 1);			info.length = code.type;			if (code.type === 18) {				info.checkBit = code.checkBit;			}			// 记录cache			this.cache[id].info = info;			return info;		}		// 仿造一个号		,		makeID : function(isFifteen) {			var GB2260 = this.GB2260 || null;			// 地址码			var addr = null;			if (GB2260 !== null) {				var loopCnt = 0;				while (addr === null) {					// 防止死循环					if (loopCnt > 10) {						addr = 110101;						break;					}					var prov = util.str_pad(util.rand(50), 2, '0');					var city = util.str_pad(util.rand(20), 2, '0');					var area = util.str_pad(util.rand(20), 2, '0');					var addrTest = [ prov, city, area ].join('');					if (GB2260[addrTest]) {						addr = addrTest;						break;					}				}			} else {				addr = 110101;			}			// 出生年			var yr = util.str_pad(util.rand(99, 50), 2, '0');			var mo = util.str_pad(util.rand(12, 1), 2, '0');			var da = util.str_pad(util.rand(28, 1), 2, '0');			if (isFifteen) {				return addr + yr + mo + da						+ util.str_pad(util.rand(999, 1), 3, '1');			}			yr = '19' + yr;			var body = addr + yr + mo + da					+ util.str_pad(util.rand(999, 1), 3, '1');			// 位置加权			var posWeight = [];			for (var i = 18; i > 1; i--) {				var wei = util.weight(i);				posWeight[i] = wei;			}			// 累加body部分与位置加权的积			var bodySum = 0;			var bodyArr = body.split('');			for (var j = 0; j < bodyArr.length; j++) {				bodySum += (parseInt(bodyArr[j], 10) * posWeight[18 - j]);			}			// 得出校验码			var checkBit = 12 - (bodySum % 11);			if (checkBit == 10) {				checkBit = 'X';			} else if (checkBit > 10) {				checkBit = checkBit % 11;			}			checkBit = (typeof checkBit === 'number' ? checkBit.toString()					: checkBit);			return (body + checkBit);		}	};// _IDValidator	GB2260 = GB2260 == null ? "" : GB2260;	return new _IDValidator(GB2260);}

调用如下:

JavaScript

//新建普通实例var Validator = new IDValidator();//验证号码是否合法,合法返回true,不合法返回falseValidator.isValid(code);//号码合法时返回分析信息(地区、出生日期、性别、校验位),不合法返回falseValidator.getInfo(code);//仿造一个18位身份证号Validator.makeID();//仿造一个15位身份证号Validator.makeID(true);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

//新建普通实例

var Validator = new IDValidator();

 

//验证号码是否合法,合法返回true,不合法返回false

Validator.isValid(code);

 

//号码合法时返回分析信息(地区、出生日期、性别、校验位),不合法返回false

Validator.getInfo(code);

 

//仿造一个18位身份证号

Validator.makeID();

 

//仿造一个15位身份证号

Validator.makeID(true);

 

Demo:

下载:查看下载

转载于:https://my.oschina.net/u/2338362/blog/1522982

你可能感兴趣的文章
将 ASP.NET Core 2.0 项目升级至 ASP.NET Core 2.1 RC 1
查看>>
js提交图片转换为base64
查看>>
学习CodeIgniter框架之旅(二)继承自定义类
查看>>
Y2161 Hibernate第三次考试 2016年8月18日 试卷分析
查看>>
Angular CLI 使用教程指南参考
查看>>
PHP 程序员的技术成长规划
查看>>
用于守护进程的出错处理函数
查看>>
memcached 分布式聚类算法
查看>>
禁止body滚动允许div滚动防微信露底
查看>>
Xtreme8.0 - Kabloom dp
查看>>
jquery css3问卷答题卡翻页动画效果
查看>>
MDK5.00中*** error 65: access violation at 0xFFFFFFFC : no 'write' permission的一种解决方法
查看>>
Android 集成支付宝支付详解
查看>>
SQL分布式查询、跨数据库查询
查看>>
C#------连接SQLServer和MySQL字符串
查看>>
Arcgis Licensemanager 不能启动的原因之一(转载)
查看>>
(原)Android在子线程用handler发送的消息,主线程是怎么loop到的?
查看>>
$digest already in progress 解决办法——续
查看>>
虚拟机 centos设置代理上网
查看>>
Struts2中Date日期转换的问题
查看>>