PHP验证身份证号码是否合法、身份证格式是否正确

admin 2022-10-27 18:04:45 2222

中华人民共和国居民身份证是用于证明居住在中华人民共和国境内的公民身份证明文件。在1984年前写作“身份证”。1984年4月6日国务院发布《中华人民共和国居民身份证试行条例》,并且开始颁发第一代居民身份证。
2003年6月28日,第十届全国人大常委会第3次会议通过《中华人民共和国居民身份证法》,2003年6月28日经主席令第4号公布;
2004年3月29日起,中国大陆正式开始为居民换发内置非接触式IC卡智能芯片的第二代居民身份证,二代身份证表面采用防伪膜和印刷防伪技术,使用个人彩色照片,并可用机器读取数字芯片内的信息。
2018年2月7日,北京警方通报:2018年将适时推出居民身份证自助办理服务和流动人口微信办理居住证等相关事宜。 
央行宣布,自2018年4月9日开始,部分城市和地区开展失效居民身份证信息和非居民身份证件信息核查试点工作。自2018年4月1日起,停征首次申领居民身份证工本费。

那么,我们如何用php验证其是否合法呢?代码如下

<?php
/**
 * 验证身份证真伪
 * @param  string  $num
 * @return bool
 */
function check_idcard($num = ''){
    $length = strlen($num);
    if ($length == 15) { //如果是15位身份证

        //15位身份证没有字母
        if (!is_numeric($num)) {
            return false;
        }
        // 省市县(6位)
        $areaNum = substr($num, 0, 6);
        // 出生年月(6位)
        $dateNum = substr($num, 6, 6);
    } else {
        if ($length == 18) { //如果是18位身份证

            //基本格式校验
            if (!preg_match('/^\d{17} [0-9xX]$/', $num)) {
                return false;
            }
            // 省市县(6位)
            $areaNum = substr($num, 0, 6);
            // 出生年月日(8位)
            $dateNum = substr($num, 6, 8);
        } else { //假身份证
            return false;
        }
    }

    $provinceCode = substr($areaNum, 0, 2);

    // 根据GB/T2260—999,省市代码11到65
    if (11 > $provinceCode || $provinceCode > 65) {
        return false;
    }

    //验证日期
    if (strlen($dateNum) == 6) { //15位身份证号没有年份,这里拼上年份
        $dateNum = '19'.$dateNum;
    }
    $year = intval(substr($dateNum, 0, 4));
    $month = intval(substr($dateNum, 4, 2));
    $day = intval(substr($dateNum, 6, 2));

    //日期基本格式校验
    if (!checkdate($month, $day, $year)) {
        return false;
    }

    //日期格式正确,但是逻辑存在问题(如:年份大于当前年)
    $currYear = date('Y');
    if ($year > $currYear) {
        return false;
    }

    //验证最后一位
    if (strlen($num) == 18) {
        $factor =  [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        $tokens =  ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];

        $checkSum = 0;
        for ($i = 0; $i < 17; $i++) {
            $checkSum += intval($num [$i]) * $factor [$i];
        }

        $mod = $checkSum % 11;
        $token = $tokens [$mod];

        $lastChar = strtoupper($num [17]);

        if ($lastChar != $token) {
            return false;
        }
    }

    return true;
}

 

下面介绍一下身份证的合法规范


身份证生成算法

我国自1999年实施公民身份号码制度以来,许多公民身份号码末位为“X”的公民,由于不明白“X”的含义,要求给予更换,产生了不必要的误会。目前我国公民身份证号码由18位数字组成:前6位为地址码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。检验码分别是“0、1、2、……10”共11个数字,当检验码为“10”时,为了保证公民身份证号码18位,所以用“X”表示。虽然校验码为“X”不能更换,但若需全用数字表示,只需将18位公民身份号码转换成15位居民身份证号码,去掉第7至8位和最后1位3个数码。

  当今的身份证号码有15位和18位之分。1985年我国实行居民身份证制度,当时签发的身份证号码是15位的,1999年签发的身份证由于年份的扩展(由两位变为四位)和末尾加了效验码,就成了18位。这两种身份证号码将在相当长的一段时期内共存。

中国大陆新身份证号码算法

1、号码的结构

公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

2、地址码

表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。(所有区域的编码可以到这个网站http://www.stats.gov.cn/tjbz/index.htm查询到最新的县及县以上的行政编码资料。) 

3、出生日期码

表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。

4、顺序码

表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

5、校验码

第十八位数字的计算方法为: 

1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2

2.将这17位数字和系数相乘的结果相加。 

3.用加出来和除以11,看余数是多少 

4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。

5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。

例如:某男性的身份证号码是101010101010101010。我们要看看这个身份证是不是合法的身份证。 

首先:我们得出,前17位的乘积和是5

然后:用5除以11得出的结果是5。 

最后:通过对应规则就可以知道余数5对应的数字是7。所以,这是一个非法的身份证号码,按说我们通过生日一眼就可以看出是假的。

所以用前17位组成的正确ID应该是101010101010101017。

可爱猫?Telegram电报群 https://t.me/ikeaimao

社区声明 1、本站提供的一切软件、教程和内容信息仅限用于学习和研究目的
2、本站资源为用户分享,如有侵权请邮件与我们联系处理敬请谅解!
3、本站信息来自网络,版权争议与本站无关。您必须在下载后的24小时之内,从您的电脑或手机中彻底删除上述内容
最新回复 (1)
  • wangsanqu 2023-2-19 只看Ta
    引用 2
    哈哈,不错哦!
    0

您可以在 登录 or 注册 后,对此帖发表评论!

返回