web项目中使用JS验证用户实名信息(含免费版和收费版)
程序员文章站
2022-07-03 17:09:10
...
开始
验证用户的实名信息,也就是判断用户填入的身份证号、姓名是否正确,是否匹配。
方法有两个大种类:
1、免费手撸验证
此验证方式只能验证身份证号码是否正确(身份证号有自验证算法),姓名只能用正则粗略验证,且无法证明身份证号与姓名匹配,但好处是免费。适合初创团队或者对实名信息有误差可容忍的项目。
2、收费型api接口
就是我们将身份证号和姓名发给这些api接口站点,由他们进行验证并且回馈给我们精准的结果。但缺点是收费,且不便宜。部分服务商单次验证结果身份证匹配才收费,不匹配不收费,这样的服务商还比较良心。
一、免费手撸验证代码
撸代码前一定要知晓原理:
目前我们使用的二代身份证有18位,其中
1-6位出生地编码(纯数字);
7-10位出生年份(纯数字);
11-12位出生月份(纯数字);
13-14位出生日期(纯数字);
15-16位出生顺序编号(纯数字);
17位性别标号(纯数字,男性为奇数,女性为偶数);
18位效验码(可能为数字或字母X);
校验原理:
根据前面十七位数字码,按照ISO7064:1983.MOD11-2校验码计算出第18位效验码,通俗的讲,身份证号码的最后一位,是由前17位计算而来的。
所以手撸验证身份证号码的方法是防不住绞尽脑汁要通关的人,只能作为一个检验工具,起到防止输错的作用。
ISO7064:1983.MOD11-2校验方式
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11,余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X -9-8-7-6-5-4-3-2。
4、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字X。
js代码(含其他工具集):
//身份证工具类
var idcardUtil = function () {
//校验身份证号码是否正确,返回true/false
var verify = function (idcard) {
//省份码,验证前两位是否正确
var provinces = '#11#12#13#14#15#21#22#23#31#32#33#34#35#36#37#41#42#43#44#45#46#50#51#52#53#54#61#62#63#64#65#71#81#82#';
var province = idcard.substr(0, 2);
if (provinces.indexOf(province) == -1) {//前两位为省份
return false;
}
//验证生日日期的格式是否正确(避免比如2月31日的错误)
var birthday_year = idcard.substr(6, 4);
var nowYear = new Date().getFullYear();
if (Number(birthday_year) < 1900 || Number(birthday_year) > nowYear) {
return false;
}
var birthday_month = idcard.substr(10, 2);
if (Number(birthday_month) > 12 || Number(birthday_month) < 1) {
return false;
}
var birthday_date = idcard.substr(12, 2);
var isLeapYear = false;
if (birthday_year % 100 == 0 && birthday_year % 400 == 0) {//世纪年
isLeapYear = true;
} else if (birthday_year % 4 == 0 && birthday_year % 100 != 0) {//普通年
isLeapYear = true;
}
var month31 = '#1#3#5#7#8#10#12#';//31天的月份
if (birthday_month == 2) {
if (isLeapYear && birthday_date >= 29) {
return false;
}
if (!isLeapYear && birthday_date >= 28) {
return false;
}
}
if (month31.indexOf(Number(birthday_month)) == -1 && birthday_month == 31) {
return false;
}
if (Number(birthday_date) > 31 || Number(birthday_date) < 1) {
return false;
}
//开始计算校验码
var x17 = 0;
var ratios = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
var result = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
for (var n in idcard) {
if (n <= 16) {
x17 += Number(idcard[n]) * ratios[n];
}
}
if (idcard[17] != result[x17 % 11]) { //计算余数
return false;
}
return true;
};
//根据身份证号计算性别,男性返回1,女性返回0
var getGender = function (idcard) {
var num = idcard.substring(16, 17);
return (num % 2 == 0) ? '0' : '1';
};
//根据身份证号计算年龄
var getAge = function (idcard) {
var birthdayStr = idcard.substring(6, 10) + '-' + idcard.substring(10, 12) + '-' + idcard.substring(12, 14);
var returnAge;
var strBirthdayArr = birthdayStr.split("-");
var birthYear = strBirthdayArr[0];
var birthMonth = strBirthdayArr[1];
var birthDay = strBirthdayArr[2];
d = new Date();
var nowYear = d.getFullYear();
var nowMonth = d.getMonth() + 1;
var nowDay = d.getDate();
if (nowYear == birthYear) {
returnAge = 0; // 同年 则为0岁
} else {
var ageDiff = nowYear - birthYear; // 年之差
if (ageDiff > 0) {
if (nowMonth == birthMonth) {
var dayDiff = nowDay - birthDay; // 日之差
if (dayDiff < 0) {
returnAge = ageDiff - 1;
} else {
returnAge = ageDiff;
}
} else {
var monthDiff = nowMonth - birthMonth; // 月之差
if (monthDiff < 0) {
returnAge = ageDiff - 1;
} else {
returnAge = ageDiff;
}
}
} else {
returnAge = -1; // 返回-1 表示出生日期输入错误 晚于今天
}
}
return returnAge; // 返回周岁年龄
};
//获取身份证号内的生日日期
var getBirthday = function (idcard) {
var birthday_year = idcard.substr(6, 4);
var birthday_month = idcard.substr(10, 2);
var birthday_date = idcard.substr(12, 2);
return birthday_year + '-' + birthday_month + '-' + birthday_date;
};
return {verify: verify, getGender: getGender, getAge: getAge, getBirthday: getBirthday};
}();
二、收费版API接口校验
这些是收费接口,会玩他们产品的人越多,他们越挣钱。
所以去往官网,有很详细的开发文档,遇到问题打客服也是秒回,非常容易就能融入代码,所以这里不赘述。
但是这里提几个优化的建议:
- 先进行第一步的本地校验,然后再上传第三方api接口进行验证,这样可以免去一些用户填写错误带来的消耗,节约成本。
- 可以将每次实名成功后的用户信息,储存在公司专用的用户实名信息数据库内,以后所有项目需要进行实名认证的时候,先本地校验,然后搜公司用户实名数据库,没有搜到,再去使用第三方接口进行校验。这样,当用户量成规模后,将减少不少用户成本。(大前提,需要写在用户守则中让用户同意,且若数据泄露公司负有法律责任,总之需要详细阅读法律)
-end
有错误请指正,有疑问请留言,谢谢