用Java程序实现身份证验证?

如何根据下面要求实现身份证校验

新的身份证号码采用GB11643-1999国家标准编制,由18位数字组成:前6位为行政区划代码,第7至14位为出生日期码,第15至17位为顺序码,女性的17位数字为偶数,男性为奇数;第18位为校验码。原15位身份证可在原两位出生年份的基础上补充两位,形成完整的出生年份信息后,在号码的最后加入校验码升级为18位新号码。第18位校验码计算的方法如下:

(1)将身份证号码前17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7910584216379105842。

(2)将身份证号码的前17位数字和对应的系数相乘,再对结果求和,然后用此和除以11求余数,余数只可能有012345678910这11个数字。

(3)余数012345678910分别对应身份证最后一位的校验码为10X 98765432(校验码为X时,实际上采用的是罗马数字10的写法,在此X为大写字母)。

按照上述步骤计算出的前17位身份证的校验码和待验证身份证号码的最后一位字符相一致时,则此身份证为有效证件号。


public static boolean checkID(String id) {
    if (id == null || id.length() != 18) { // 身份证号码长度不为18位,直接返回false
        return false;
    }
    int[] coefficients = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; // 前17位数的系数
    char[] valids = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; // 余数对应的校验码
    int sum = 0; // 前17位数和系数乘积之和
    for (int i = 0; i < 17; i++) {
        char c = id.charAt(i);
        if (c < '0' || c > '9') { // 前17位数中有非数字
            return false;
        }
        sum += (c - '0') * coefficients[i];
    }
    int remainder = sum % 11; // 取余数
    char valid = valids[remainder]; // 余数对应的校验码
    char last = id.charAt(17); // 身份证号码的最后一位
    if (valid == last) {
        return true; // 校验码正确,返回true
    } else {
        return false; // 校验码不正确,返回false
    }
} 
package com.liu.susu.message.utils;


import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* description :身份证校验工具类
*/
public class IdCardCheckUtil {

    /**
     * 位权值数组
     */
    private static int[] weightCode = new int[17];

    /**
     * 身份证校验码(末尾)
     * 用来比对计算的余数
     */
    private static final String[] CHECK_CODE = {"1","0","X","9","8","7","6","5","4","3","2"};

    /**
     * 除数11(身份证算法求余关键值)
     */
    private static final int DIVIDER = 11;

    /**
     * 身份证前6位占的字符数(地区6位)
     */
    private static final int AREA_NUMBER = 6;

    /**
     * 新身份证年份标志(比如:1989年取19)
     * 旧身份证号与新身份证号的区别是:新的去掉年份和最后一位就是旧的证件号
     */
    private static final String YEAR_PREFIX = "19";

    private static final int OLD_ID_CARD_LENGTH = 15;

    private static final int NEW_ID_CARD_LENGTH = 18;


    static {
        //1. 初始化位权值数组
        setWiBuffer();
    }

    /**
     * description :获取位权值数组
     * @param
     * @return void
     * @author susu
     */
    private static void setWiBuffer() {
        for (int i = 0; i < weightCode.length; i++) {
            int k = (int) Math.pow(2, (weightCode.length - i));
            weightCode[i] = (k % DIVIDER);
        }
    }

    /**
     * description :校验身份证入口
     * @param idCard
     * @return boolean
     * @author susu
     */
    public static boolean checkIdCardProc(final String idCard) {
        if (checkLengthAndBirthday(idCard)) {
            return idCard.length() == OLD_ID_CARD_LENGTH ? true : checkIdCard18(idCard);
        }
        return false;
    }

    /**
     * description :2.校验身份证长度 和 出生日期 和正则校验
     * @param idCard
     * @return boolean
     * @author susu
     */
    private static boolean checkLengthAndBirthday(final String idCard) {
        if ((idCard.length() == OLD_ID_CARD_LENGTH) || (idCard.length() == NEW_ID_CARD_LENGTH)) {
            return regexCheckAndCheckBirthday(idCard);
        }
        return false;
    }

    /**
     * description :3.校验身份证中的日期是否合法(含正则校验)
     * @param idCard
     * @return boolean
     * @author susu
     */
    private static boolean regexCheckAndCheckBirthday(final String idCard) {
        String birthday = "";
        /**
         * 1. 加一层正则校验
         * 2. 获取证件号的出生日期的字符串:格式如:20221121
         */
        if (idCard.length() == OLD_ID_CARD_LENGTH) {
            //15位的身份证号没有校验码,所以最好用正则校验一下
            if (idCard15RegexCheck(idCard)) {
                birthday = YEAR_PREFIX + idCard.substring(AREA_NUMBER, AREA_NUMBER + 6);
            }
        } else {
            //18位的不用正则校验也行
            if (idCard18RegexCheck(idCard)) {
                birthday = idCard.substring(AREA_NUMBER, AREA_NUMBER + 8);
            }
        }
        System.out.println("birthday->" + birthday);
        return checkStrDate(birthday);
    }

    /**
    * description :最后,校验身份证最后一位检验码是否正确
    * @param idCard
    * @return boolean
    * @author susu
    */
    public static boolean checkIdCard18(final String idCard) {
        //1.获取余数
        int dividedResult = getDividedResult(idCard);
        //2.根据余数获取对应的身份证校验码
        String code = CHECK_CODE[dividedResult];
        //3.获取身份证的最后一位(第18位),然后校验
        String lastStr = idCard.substring(idCard.length() - 1);
        if (code.equals(lastStr)) {
            return true;
        }
        return false;
    }

    /**
     * description :根据前17位加权求和 获取余数
     * @param idCard
     * @return int
     * @author susu
     */
    public static int getDividedResult(String idCard) {
        //先获取前17位数
        String[] idCardNum = idCard.substring(0, 17).split("");
        int sum = 0;
        for (int i = 0; i < idCardNum.length; i++) {
            sum += Integer.parseInt(idCardNum[i]) * weightCode[i];
        }
        return sum % DIVIDER;
    }

    /*
     * "\\d{8}"                  1~6位分别代表省市县,只校验是否数字。
     *                              7~8位代表年份后两位数字
     * "(0[1-9]|1[012])"          9~10位代表月份,01~12月
     *     "(0[1-9]|[12]\\d|3[01])"  11~12位代表日期,1~31日
     *     "\\d{3}"                  13~15位为三位顺序号
     */
    private static boolean idCard15RegexCheck(String idCard) {
        String reg = "^(\\d{8}(0[1-9]|1[012])(0[1-9]|[12]\\d|3[01])\\d{3})$";
        Pattern pattern = Pattern.compile(reg);
        Matcher m = pattern.matcher(idCard);
        return (m.matches()) ? true : false;
    }

    /*
     * "\\d{6}"                  1~6位分别代表省市县,只校验是否数字。
     *     "(18|19|20)\\d{2}"       7~10位代表年份,先管18,19,20,下个世纪的让下个世纪的人去校验
     *     "(0[1-9]|1[012])"        11~12位代表月份,01~12月
     *     "(0[1-9]|[12]\\d|3[01])"  13~14位代表日期,1~31日
     *     "\\d{3}"                  15~17位为三位顺序号
     *     "(\\d|X|x)"               18位为校验位数字,允许字母x和X
     */
    private static boolean idCard18RegexCheck(String idCard) {
        String reg = "^(\\d{6}(18|19|20)\\d{2}(0[1-9]|1[012])(0[1-9]|[12]\\d|3[01])\\d{3}(\\d|X|x))$";
        Pattern pattern = Pattern.compile(reg);
        Matcher m = pattern.matcher(idCard);
        return (m.matches()) ? true : false;
    }

    /**
    * description :校验8位日期是否合法(比如:20021122)
    * @param strDate
    * @return boolean
    * @author susu
    */
    private static boolean checkStrDate(final String strDate) {
        try {
            LocalDate.parse(strDate, DateTimeFormatter.ofPattern("yyyyMMdd"));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    public static void main(String[] args) {

        String id2 = "XXXX";

        boolean b2 = checkIdCardProc(id2);
        System.out.println(b2);

    }

}

https://blog.csdn.net/suixinfeixiangfei/article/details/128167595

您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632不知道你这个问题是否已经解决, 如果还没有解决的话:

本系列是博主为了督促自己在博士期间能够静下心来完成科研开设,并将我在学习期间的感悟或者心得记录下来,如果能帮到你那么再好不过。

Note:本系列有两篇 如何写好一篇论文 是博主在阅读John H. Cochrane的Writing Tips for Ph. D. Students一文,Michael KremerWriting Papers: A Checklist以及观看 Simon Peyton Jones关于How to write a great research paper的演讲,分别从论文整体注意事项、论文写作清单和论文每一个部分的具体写作要点和技巧入手,总结了如何写好一篇学术论文,希望大家能够仔细阅读一定会有所收获。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^