web项目中使用JS验证用户实名信息(含免费版和收费版)

开始

验证用户的实名信息,也就是判断用户填入的身份证号、姓名是否正确,是否匹配。

方法有两个大种类:

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
有错误请指正,有疑问请留言,谢谢

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值