Javascript驗證表單身份證號碼的合法性
文章出處:
不少大的遊戲註冊時都要輸入身份證號碼,來限制未成年人,配合所謂的反沉迷系統,賬號註冊環節注重的是快捷,所以身份證驗證都不是真實的驗證,只是根據身份證格式簡單判斷是否合法而已,騙騙小學生,當然也不是那麼簡單。昨天研究了下身份證表單驗證,用javascript寫一個身份證號碼的驗證程式,和盛大賬號註冊的身份證驗證基本差不多。如果有興趣可以瞭解下~
首先要知道我國身份證號碼的規則,我國的身份證為18位,老的身份證是15位。GB11643-1999《公民身份號碼》中做了明確的規定:公民身份號碼是特徵組合碼,由十七位數字本體碼和一位數字校驗碼組成。排列順序從左至右依次為:六位數字地址碼,八位數字出生日期碼,三位數字順序碼和一位數字校驗碼。
地址碼:身份證前6位,表示編碼物件常住戶口所在縣(市、旗、區)的行政區劃程式碼。1-2位為省編號,3-4位為市編號,5-6位為縣區編號。
各省編號為: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:”澳門”,91:”國外”,目前共有34個省級行政區,即4個直轄市、23個省、5個自治區、2個特別行政區。
出生日期碼:身份證7-12位,表示物件出生年月日,15位的身份證號碼年份為2位數。
順序碼:同一地址碼所標識的區域範圍內,對同年、月、日出生的人編定的順序號。其中13-15位為各派出所分配的號碼段,其中第17位奇數分給男性,偶數分給女性。對於同一地區同年、月、日出生的人,先到派出所上戶口的先分配編碼,以此類推。
校驗碼:身份證最後一位,根據前面十七位數字碼,按照ISO 7064:1983.MOD 11-2校驗碼計算出來的檢驗碼。計算規則如下:
1、將前面的身份證號碼17位數分別乘以不同的係數。從第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。
由上文可知,要檢驗一個身份證號碼是否合法,可以檢驗省份程式碼、出生日期和校驗碼這三個部分結構是否正確即可。為什麼只檢驗省份程式碼?我國目前有7000多個縣區,要一一檢查6位地址碼沒必要,所以前端只要簡單檢驗下省份程式碼就行了。出生日期要檢查是否有效,比如使用者輸入一個20135475這樣一個根本不存在的年月日,可以用javascript的Date()來檢驗日期是否為有效日期。校驗碼為身份證前17位數字通過一套公式算出來的,這個並不難。最後還需要檢驗如果是15位的身份證號碼,雖然我國1999年開始升18位身份證號碼,不過還是有少部分人沒有去辦理二代身份證,由於15位身份證號碼沒有校驗碼,所以只能簡單判斷省編號和出生日期了。
下面可以開始寫javascript身份證表單檢驗程式了,以下是我寫的一段簡單的javascript程式碼。
<script type="text/javascript">
window.onload=function(){
var oTxt=document.getElementById('txt');
var oBtn=document.getElementById('btn');
var CheckIdCard={
//Wi 加權因子 Xi 餘數0~10對應的校驗碼 Pi省份程式碼
Wi:[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2],
Xi:[1,0,"X",9,8,7,6,5,4,3,2],
Pi:[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,91],
//檢驗18位身份證號碼出生日期是否有效
//parseFloat過濾前導零,年份必需大於等於1900且小於等於當前年份,用Date()物件判斷日期是否有效。
brithday18:function(sIdCard){
var year=parseFloat(sIdCard.substr(6,4));
var month=parseFloat(sIdCard.substr(10,2));
var day=parseFloat(sIdCard.substr(12,2));
var checkDay=new Date(year,month-1,day);
var nowDay=new Date();
if (1900<=year && year<=nowDay.getFullYear() && month==(checkDay.getMonth()+1) && day==checkDay.getDate()) {
return true;
};
},
//檢驗15位身份證號碼出生日期是否有效
brithday15:function(sIdCard){
var year=parseFloat(sIdCard.substr(6,2));
var month=parseFloat(sIdCard.substr(8,2));
var day=parseFloat(sIdCard.substr(10,2));
var checkDay=new Date(year,month-1,day);
if (month==(checkDay.getMonth()+1) && day==checkDay.getDate()) {
return true;
};
},
//檢驗校驗碼是否有效
validate:function(sIdCard){
var aIdCard=sIdCard.split("");
var sum=0;
for (var i = 0; i < CheckIdCard.Wi.length; i++) {
sum+=CheckIdCard.Wi[i]*aIdCard[i]; //線性加權求和
};
var index=sum%11;//求模,可能為0~10,可求對應的校驗碼是否於身份證的校驗碼匹配
if (CheckIdCard.Xi[index]==aIdCard[17].toUpperCase()) {
return true;
};
},
//檢驗輸入的省份編碼是否有效
province:function(sIdCard){
var p2=sIdCard.substr(0,2);
for (var i = 0; i < CheckIdCard.Pi.length; i++) {
if(CheckIdCard.Pi[i]==p2){
return true;
};
};
}
};
oBtn.onclick=function(){
var sIdCard=oTxt.value.replace(/^\s+|\s+$/g,"");//去除字串的前後空格,允許使用者不小心輸入前後空格
if (sIdCard.match(/^\d{14,17}(\d|X)$/gi)==null) {//判斷是否全為18或15位數字,最後一位可以是大小寫字母X
alert("身份證號碼須為18位或15位數字"); //允許使用者輸入大小寫X代替羅馬數字的Ⅹ
}
else if (sIdCard.length==18) {
if (CheckIdCard.province(sIdCard)&&CheckIdCard.brithday18(sIdCard)&&CheckIdCard.validate(sIdCard)) {
alert("身份證號碼合法");
}
else{
alert("請輸入有效的身份證號碼");
};
}
else if (sIdCard.length==15) {
if (CheckIdCard.province(sIdCard)&&CheckIdCard.brithday15(sIdCard)) {
alert("身份證號碼合法");
}
else{
alert("請輸入有效的身份證號碼");
};
};
};
}
</script>
基本和盛大賬號註冊的身份證號碼驗證功能一樣。缺點只能根據身份證格式來簡單判斷是否合法,不能判斷身份證號碼和姓名的真實性,同時只要省份程式碼、出生日期和校驗碼填寫正確格式,其他亂寫也能通過,這些表單驗證只能騙騙不懂規則的小學生,
其實,完全可以虛構一個15位的身份證號碼,因為沒有複雜計算的校驗碼,只要省份程式碼和出生日期格式正確,其他的順便寫,基本能通過各種身份證的表單驗證,親測多個網站的註冊驗證屢試不爽。當然,如果真的需要確實身份證的真實性,一般像支付寶,電信,銀行等都會連線“全國公民身份資訊資料庫”,人工稽核提交的身份證姓名和資訊是否真實。個人也可以到“全國公民身份證號碼查詢服務中心”查身份證號碼,5塊錢一次。