1. 程式人生 > 其它 >揭開身份證驗證的神祕面紗

揭開身份證驗證的神祕面紗

正則驗證身份證號碼

HTML5學堂:曾經一直覺得用正則驗證身份證號碼是很簡單的~但是,當真正挖掘身份證號碼的規則之後,才發現,想要寫好一個正則驗證也沒有那麼容易。最近一週利利出差,所以,只能週六跟大家一起分享一下自己的研究結果啦~

身份證的規則

書寫一個正則之前,需要先了解一下身份證的基本規則

  1. /*
  2. * 身份證18位編碼規則:dddddd yyyymmdd xxx y
  3. * dddddd:6位地區編碼
  4. * yyyymmdd: 出生年(四位年)月日,如:19910215
  5. * xxx:順序編碼,系統產生,無法確定,奇數為男,偶數為女
  6. * y: 校驗碼,該位數值可通過前17位計算獲得
  7. * HTML5學堂出品 http://www.h5course.com 請尊重原創
  8. * 前17位號碼加權因子為 Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]
  9. * 驗證位 Y = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]
  10. * 如果驗證碼恰好是10,為了保證身份證是十八位,那麼第十八位將用X來代替
  11. */

校驗位計算方法:身份證前17位,每一位數字和相應位數的加權因子進行乘法運算,之後求和(17項之和),再用這個和對11取餘,所得的餘數作為“驗證位陣列Y”的下標,也就是Y[餘數],找到“驗證位陣列Y”中的相應數字,如果身份證最後一位和這個數字吻合,則身份證號碼合法(如果最後一位是X/x,就對應於“驗證位陣列Y”中的10這個數字)

簡單的號碼計算小例子

假如是這個身份證號碼(這個身份證號碼是我瞎編的):110203198811120342。

於是,複雜的計算開始了。取出身份證前17位,與[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]中對應的位分別進行乘法運算,於是乎:

sum = 1 * 7 + 1 * 9 + 0 * 10 + 2 * 5 + ... + 3 * 4 + 4 * 2。

我們能夠計算出來,總和為177。之後用177對11取餘,餘數為1。那麼在[1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2]陣列中,下標為1的元素就是第二個元素,也就是數值為0。此時將0與身份證號的最後一位(2)做比較,很明顯,錯誤,那麼也證明了這個號碼是我瞎編的了……

驗證身份證號碼的正則如何寫?

身份證規則

我們將一個身份證號碼拆開:身份證18位編碼規則:dddddd yyyymmdd xxx y

1) dddddd:6位地區編碼,地區編碼沒有以0開頭的,舉一個例子,北京用的就是110開頭,河北用的就是130開頭,福建省用的是350開頭,此類。

2) yyyymmdd: 出生年(四位年)月日,前四位是年份,沒啥可說的,月份只能是01~12,日期只能是01~31

3) xxx:三位數字

4) y: 校驗碼,0~9以及X(有時有人會寫成x)

相對應的正則出爐嘍

1) 地區編碼:[1-9]d{5}

2) 出生年份:[1-9]d{3}

3) 出生月份:((0[1-9])|(1[0-2]))

4) 出生日期:((0[1-9])|([1-2]d)|(3[0-1]))

5) 最後四位:((d{4})|(d{3}[Xx]))

完整匹配身份證號碼的正則

於是乎,完整匹配身份證號碼的正則華麗麗的誕生了~~~

  1. var reg = /^[1-9]d{5}[1-9]d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]d)|(3[0-1]))((d{4})|(d{3}[Xx]))$/;

完了嗎?別急,往下接著看~~~

使用JS增強號碼的可控性

利利此處採用的是返回物件的設定方式,主要是便於獲取完整的資訊,需要注意的就是要在返回時提供比較合理的API了,不然對方是看不懂滴~~~

我們希望使用者通過呼叫驗證身份證號碼的方法,不僅僅能夠得到是否正確,還能夠得到更加詳細的資訊。所以,一起先來看程式碼嘍~

/*
* 功能:驗證身份證是否可用,如果可用,則提取生日、性別等資訊
* 引數:傳入一個字串或者一個數字均可
* 返回:包含基本資訊的物件
* 作者:HTML5學堂 http://www.h5course.com
*/
function regIDAllInf(str){
    str = str.toString();
    var reg = /^[1-9]d{5}[1-9]d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]d)|(3[0-1]))((d{4})|(d{3}[Xx]))$/;
    // 用於儲存結果
    var result = {};
    if (reg.test(str)) {
        var sum = 0;
        var arrID = str.split("");
        var arrWi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        var arrY = [1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2];
        for (var i = 0; i < arrWi.length; i++) {
            sum += arrID[i] * arrWi[i];
        };
        sum %= 11;
        var lastID = arrID[arrID.length - 1];
        if (lastID == "X" || lastID == "x") {
            lastID = 10;
        };
        if (arrY[sum] == lastID) {
            result["check"] = true;
            result["birthday"] = str.substr(6, 8);
            result["cityCode"] = str.substr(0, 6);
            result["gender"] = (str.substr(14, 3) % 2 == 0) ? "女" : "男";
        } else {
            result["check"] = false;
            result["error"] = "身份證號碼輸入錯誤";
        }
    } else {
        result["check"] = false;
        result["error"] = "身份證號碼格式有誤";
    }    
    return result;
}
console.log(regIDAllInf(str)); // 此處請將str替換為身份證號碼進行測試

如果格式正確,會返回匹配正確,並返回性別、區域、生日的資訊。如果錯誤,也會根據情況返回不同的錯誤提示資訊。

本文章內容小編:HTML5學堂-利利。耗時4h~