06Java身份證校驗工具

/**
 *<html>
 *<body>
 *  <P> Copyright  ● JasonInternational </p>
 *  <p> All rights reserved.</p>
 *  <p> Created by Jason see https://github.com/Jasonandy/springboot-wx </p>
 *</body>
 *</html>
 */
package cn.ucaner.skeleton.common.utils.base;

import java.util.regex.Pattern;

/**
* @Package:cn.ucaner.wx.app.core.utils.base   
* @ClassName:IdcardValidator   
* @Description:   <p> --15位身份證號碼:第7、8位為出生年份(兩位數(shù))汽煮,第9赶盔、10位為出生月份,第11、12位代表出生日期失都,第15位代表性別立润,奇數(shù)為男,偶數(shù)為女蟋滴。
* --18位身份證號碼 :第7染厅、8、9津函、10位為出生年份(四位數(shù))肖粮,第11、第12位為出生月份尔苦,第13涩馆、14位代表出生日期,第17位代表性別允坚,奇數(shù)為男魂那,偶數(shù)為女。
* </p>
* @Author: - Jason   
* @CreatTime:2018年7月24日 上午10:s46:18   
* @Modify By:   
* @ModifyTime:  2018年7月24日
* @Modify marker:   
* @version    V1.0
 */
public class IdcardValidator {

    /**
     * 省稠项,直轄市代碼表: { 11:"北京",12:"天津",13:"河北",14:"山西",15:"內(nèi)蒙古",
     * 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:"澳門",91:"國外"}
     */

    // 每位加權(quán)因子
    private static int power[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };

    /**
     * 驗證身份證是否合法
     * @param idcard
     * @return
     */
    @SuppressWarnings("static-access")
    public boolean isValidatedAllIdcard(String idcard) {
        return this.isValidate18Idcard(idcard);
    }

    /**
     * 
     <p>
     * 判斷18位身份證的合法性
     * </p>
     * 根據(jù)〖中華人民共和國國家標(biāo)準(zhǔn)GB11643-1999〗中有關(guān)公民身份號碼的規(guī)定涯雅,公民身份號碼是特征組合碼,由十七位數(shù)字本體碼和一位數(shù)字校驗碼組成展运。
     * 排列順序從左至右依次為:六位數(shù)字地址碼斩芭,八位數(shù)字出生日期碼,三位數(shù)字順序碼和一位數(shù)字校驗碼乐疆。
     * <p>
     * 順序碼: 表示在同一地址碼所標(biāo)識的區(qū)域范圍內(nèi)划乖,對同年、同月挤土、同 日出生的人編定的順序號琴庵,順序碼的奇數(shù)分配給男性,偶數(shù)分配 給女性。
     * </p>
     * <p>
     * 1.前1迷殿、2位數(shù)字表示:所在省份的代碼儿礼; 2.第3、4位數(shù)字表示:所在城市的代碼庆寺; 3.第5蚊夫、6位數(shù)字表示:所在區(qū)縣的代碼;
     * 4.第7~14位數(shù)字表示:出生年懦尝、月知纷、日; 5.第15陵霉、16位數(shù)字表示:所在地的派出所的代碼琅轧;
     * 6.第17位數(shù)字表示性別:奇數(shù)表示男性,偶數(shù)表示女性踊挠;
     * 7.第18位數(shù)字是校檢碼:也有的說是個人信息碼乍桂,一般是隨計算機的隨機產(chǎn)生,用來檢驗身份證的正確性效床。校檢碼可以是0~9的數(shù)字睹酌,有時也用x表示。
     * </p>
     * <p>
     * 第十八位數(shù)字(校驗碼)的計算方法為: 1.將前面的身份證號碼17位數(shù)分別乘以不同的系數(shù)剩檀。從第一位到第十七位的系數(shù)分別為:7 9 10 5 8 4
     * 2 1 6 3 7 9 10 5 8 4 2
     * </p>
     * <p>
     * 2.將這17位數(shù)字和系數(shù)相乘的結(jié)果相加憋沿。
     * </p>
     * <p>
     * 3.用加出來和除以11,看余數(shù)是多少谨朝?
     * </p>
     * 4.余數(shù)只可能有0 1 2 3 4 5 6 7 8 9 10這11個數(shù)字卤妒。其分別對應(yīng)的最后一位身份證的號碼為1 0 X 9 8 7 6 5 4 3
     * 2甥绿。
     * <p>
     * 5.通過上面得知如果余數(shù)是2字币,就會在身份證的第18位數(shù)字上出現(xiàn)羅馬數(shù)字的Ⅹ。如果余數(shù)是10共缕,身份證的最后一位號碼就是2洗出。
     * </p>
     * @param idcard
     *                  待驗證的身份證
     * @return
     */
    public static boolean isValidate18Idcard(String idcard) {
        // 非18位為假
        if (idcard.length() != 18) {
            return false;
        }
        // 獲取前17位
        String idcard17 = idcard.substring(0, 17);
        // 獲取第18位
        String idcard18Code = idcard.substring(17, 18);
        char c[] = null;
        String checkCode = "";
        // 是否都為數(shù)字
        if (isDigital(idcard17)) {
            c = idcard17.toCharArray();
        } else {
            return false;
        }

        if (null != c) {
            int bit[] = new int[idcard17.length()];
            bit = converCharToInt(c);
            int sum17 = 0;
            sum17 = getPowerSum(bit);
            // 將和值與11取模得到余數(shù)進行校驗碼判斷
            checkCode = getCheckCodeBySum(sum17);
            if (null == checkCode) {
                return false;
            }
            // 將身份證的第18位與算出來的校碼進行匹配,不相等就為假
            if (!idcard18Code.equalsIgnoreCase(checkCode)) {
                return false;
            }
        }
        
        return true;
    }

    /**
     * 18位身份證號碼的基本數(shù)字和位數(shù)驗校
     * 
     * @param idcard
     *                  待驗證的身份證
     * @return
     */
    public static boolean is18Idcard(String idcard) {
        return Pattern.matches("^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|x|X]{1})$", idcard);
    }

    /**
     * 數(shù)字驗證
     * @param str
     * @return
     */
    private static boolean isDigital(String str) {
        return str == null || "".equals(str) ? false : str.matches("^[0-9]*$");
    }

    /**
     * 將身份證的每位和對應(yīng)位的加權(quán)因子相乘之后图谷,再得到和值
     * 
     * @param bit
     * @return
     */
    private static int getPowerSum(int[] bit) {
        int sum = 0;
        if (power.length != bit.length) {
            return sum;
        }

        for (int i = 0; i < bit.length; i++) {
            for (int j = 0; j < power.length; j++) {
                if (i == j) {
                    sum = sum + bit[i] * power[j];
                }
            }
        }
        
        return sum;
    }

    /**
     * 將和值與11取模得到余數(shù)進行校驗碼判斷
     *
     * @param sum17
     * @return
     */
    private static String getCheckCodeBySum(int sum17) {
        String checkCode = null;
        switch (sum17 % 11) {
        case 10:
            checkCode = "2";
            break;
        case 9:
            checkCode = "3";
            break;
        case 8:
            checkCode = "4";
            break;
        case 7:
            checkCode = "5";
            break;
        case 6:
            checkCode = "6";
            break;
        case 5:
            checkCode = "7";
            break;
        case 4:
            checkCode = "8";
            break;
        case 3:
            checkCode = "9";
            break;
        case 2:
            checkCode = "x";
            break;
        case 1:
            checkCode = "0";
            break;
        case 0:
            checkCode = "1";
            break;
        }
        return checkCode;
    }

    /**
     * 將字符數(shù)組轉(zhuǎn)為整型數(shù)組
     * @param c
     * @return
     * @throws NumberFormatException
     */
    private static int[] converCharToInt(char[] c) throws NumberFormatException {
        int[] a = new int[c.length];
        int k = 0;
        for (char temp : c) {
            a[k++] = Integer.parseInt(String.valueOf(temp));
        }
        return a;
    }
    
    /**
     * @param idno
     * @return 身份證信息中代表性別的數(shù)值
     */
    public static int getUserSex(String idno) {
        String sex="1";
        if(idno!=null){
            if(idno.length()>15){
                sex = idno.substring(16, 17);
            }
        }
        
        return Integer.parseInt(sex) % 2==0 ? 0:1;
    }
    
    /**
     * @Description: Just for test
     * @param {@link http://www.creditsailing.com/HuaDangZiXun/653900.html}
     * @Autor: jasonandy@hotmail.com
     */
    public static void main(String[] args) {
        //360822198904022764
        //360822198403133298
        //360822199207227275
        System.out.println(is18Idcard("360822199207227275"));
        System.out.println(getUserSex("360822198403133298"));
    }
}


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翩活,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子便贵,更是在濱河造成了極大的恐慌菠镇,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件承璃,死亡現(xiàn)場離奇詭異利耍,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門隘梨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來程癌,“玉大人,你說我怎么就攤上這事轴猎∏独颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵捻脖,是天一觀的道長锐峭。 經(jīng)常有香客問我,道長郎仆,這世上最難降的妖魔是什么只祠? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮扰肌,結(jié)果婚禮上抛寝,老公的妹妹穿的比我還像新娘。我一直安慰自己曙旭,他們只是感情好盗舰,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著桂躏,像睡著了一般钻趋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剂习,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天蛮位,我揣著相機與錄音,去河邊找鬼鳞绕。 笑死失仁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的们何。 我是一名探鬼主播萄焦,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼冤竹!你這毒婦竟也來了拂封?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鹦蠕,失蹤者是張志新(化名)和其女友劉穎冒签,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钟病,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡萧恕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年霜定,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廊鸥。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡望浩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惰说,到底是詐尸還是另有隱情磨德,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布吆视,位于F島的核電站典挑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏啦吧。R本人自食惡果不足惜您觉,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望授滓。 院中可真熱鬧琳水,春花似錦、人聲如沸般堆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淮摔。三九已至私沮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間和橙,已是汗流浹背仔燕。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留魔招,地道東北人晰搀。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像仆百,于是被迫代替她去往敵國和親厕隧。 傳聞我的和親對象是個殘疾皇子奔脐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容