身份驗證之絕對驗證

import java.util.Calendar;
import java.util.Scanner;

public class ValidateID {
	/*
	 * 我國現行使用公民身份證號碼有兩種尊循兩個國家標準,〖GB 11643-1989〗和〖GB 11643-1999〗。
	 * 〖GB 11643-1989〗中規定的是15位身份證號碼:排列順序從左至右依次爲:六位數字地址碼,六位數字出生日期碼,三位數字順序碼,其中出生日期碼不包含世紀數。
	 * 〖GB 11643-1999〗中規定的是18位身份證號碼:公民身份號碼是特徵組合碼,由十七位數字本體碼和一位數字校驗碼組成。
	 * 排列順序從左至右依次爲:六位數字地址碼,八位數字出生日期碼,三位數字順序碼和一位數字校驗碼。
	 * 地址碼:表示編碼對象常住戶口所在縣(市、旗、區)的行政區劃代碼。
	 * 出生日期碼:表示編碼對象出生的年、月、日,其中年份用四位數字表示,年、月、日之間不用分隔符。
	 * 順序碼:表示同一地址碼所標識的區域範圍內,對同年、同月、同日出生的人員編定的順序號。
	 * 順序碼的奇數分給男性,偶數分給女性。
	 * 校驗碼:是根據前面十七位數字碼,按照ISO 7064:1983.MOD 11-2校驗碼計算出來的檢驗碼。
	 */
	
	// 記錄信息
	private String info = "地區:";

	public static void main(String[] args) {
		new ValidateID().validateId();
	}

	public void validateId() {

		System.out.println("輸入身份證號碼:");
		Scanner sc = new Scanner(System.in);
		String id = sc.nextLine();
		// 判斷是不是18位數字
		if (id.length() != 18) {
			System.out.println("輸入的位數不對");
			return;
		}
		// 如果含有非數字,則直接返回退出
		try {
			Long.parseLong(id);
		} catch (Exception e) {
			System.out.println("輸入非數字");
			return;
		}

		// 身份證代表省份的數字
		int shengfen = Integer.parseInt(id.substring(0, 2));
		
		//判斷是否有該省份,有則獲得相應信息
		if(!isArea(shengfen)){
			System.out.println("省份不對");
			return;
		}

		// 獲得身份證年份
		int nianfen = Integer.parseInt(id.substring(6, 10));
		info += "出生日期:" + nianfen + "年";
		// 獲得日期實例
		Calendar rightNow = Calendar.getInstance();
		// 獲得當前年份
		int MaxYear = rightNow.get(Calendar.YEAR);
		if ((nianfen < 1949) && (nianfen > MaxYear)) {
			System.out.println("年份不對");
			return;
		}
		// 獲得身份證月份
		int yuefen = Integer.parseInt(id.substring(10, 12));
		info += yuefen + "月";
		// 判斷月份是否正確
		if ((yuefen <= 0) && (yuefen > 12)) {
			System.out.println("月份錯誤");
			return;
		}
		// 獲得身份證日期
		int riqi = Integer.parseInt(id.substring(12, 14));
		info += riqi + "日";
		// 判斷日期是否正確
		if (riqi <= 0 && riqi > 31) {
			System.out.println("日期錯誤");
			return;
		}
		// 獲得身份證性別數字
		int sex = Integer.parseInt(id.substring(16, 17));
		// 奇數爲男,偶數爲女
		if (sex % 2 == 0) {
			info += "   性別:女";
		} else {
			info += "   性別:男";
		}
		//調用驗證身份證最後一位校驗碼函數
		if (!validateLastNum(id)) {
			System.out.println("該身份證未能通過驗證");
			return;
		}
		System.out.println("該身份證通過驗證");
		// 打印身份證信息
		System.out.println("信息如下");
		System.out.println(info);
	}
	
	//判斷該省份,並獲得省份信息
	public boolean isArea(int shengfen){
		// 判斷該省份是否存在,其中下列代碼代表不同省份,可到網上查找獲得
		if (!((shengfen == 11) || (shengfen == 12) || (shengfen == 13)
				|| (shengfen == 14) || (shengfen == 15) || (shengfen == 21)
				|| (shengfen == 22) || (shengfen == 23) || (shengfen == 31)
				|| (shengfen == 32) || (shengfen == 33) || (shengfen == 34)
				|| (shengfen == 35) || (shengfen == 36) || (shengfen == 37)
				|| (shengfen == 41) || (shengfen == 42) || (shengfen == 43)
				|| (shengfen == 44) || (shengfen == 45) || (shengfen == 46)
				|| (shengfen == 50) || (shengfen == 51) || (shengfen == 52)
				|| (shengfen == 53) || (shengfen == 54) || (shengfen == 61)
				|| (shengfen == 62) || (shengfen == 63) || (shengfen == 64)
				|| (shengfen == 65) || (shengfen == 71) || (shengfen == 81) || (shengfen == 82))) {
			System.out.println("省份不對");
			return false;
		}
		
		if (shengfen == 11) {
			info += "北京    ";
		}
		if (shengfen == 12) {
			info += "天津    ";
		}
		if (shengfen == 13) {
			info += "河北    ";
		}
		if (shengfen == 14) {
			info += "山西    ";
		}
		if (shengfen == 15) {
			info += "內蒙古    ";
		}
		if (shengfen == 21) {
			info += "遼寧    ";
		}
		if (shengfen == 22) {
			info += "吉林    ";
		}
		if (shengfen == 23) {
			info += "黑龍江    ";
		}
		if (shengfen == 31) {
			info += "上海    ";
		}
		if (shengfen == 32) {
			info += "江蘇    ";
		}
		if (shengfen == 33) {
			info += "浙江    ";
		}
		if (shengfen == 34) {
			info += "安徽    ";
		}
		if (shengfen == 35) {
			info += "福建    ";
		}
		if (shengfen == 36) {
			info += "江西    ";
		}
		if (shengfen == 37) {
			info += "山東    ";
		}
		if (shengfen == 41) {
			info += "河南    ";
		}
		if (shengfen == 42) {
			info += "湖北    ";
		}
		if (shengfen == 43) {
			info += "湖南    ";
		}
		if (shengfen == 44) {
			info += "廣東    ";
		}
		if (shengfen == 45) {
			info += "廣西壯族自治區    ";
		}
		if (shengfen == 46) {
			info += "海南    ";
		}
		if (shengfen == 50) {
			info += "重慶    ";
		}
		if (shengfen == 51) {
			info += "四川    ";
		}
		if (shengfen == 52) {
			info += "貴州    ";
		}
		if (shengfen == 53) {
			info += "雲南    ";
		}
		if (shengfen == 54) {
			info += "西藏自治區    ";
		}
		if (shengfen == 61) {
			info += "陝西    ";
		}
		if (shengfen == 62) {
			info += "甘肅    ";
		}
		if (shengfen == 63) {
			info += "青海    ";
		}
		if (shengfen == 64) {
			info += "寧夏回族自治區    ";
		}
		if (shengfen == 65) {
			info += "新疆維吾爾族自治區    ";
		}
		if (shengfen == 71) {
			info += "臺灣    ";
		}
		if (shengfen == 81) {
			info += "香港特別行政區    ";
		}
		if (shengfen == 82) {
			info += "澳門特別行政區    ";
		}
		return true;
	}


	/*
	 * 關於身份證號碼最後一位的校驗碼的算法如下: ∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 ) "*" :
	 * 表示乘號 i: 表示身份證號碼每一位的序號,從右至左,最左側爲18,最右側爲1。 a[i]: 表示身份證號碼第 i 位上的號碼 W[i]: 表示第
	 * i 位上的權值 W[i] = 2^(i-1) mod 11 設:R = ∑(a[i]*W[i]) mod 11 ( i = 2, 3, ...,
	 * 18 ) C = 身份證號碼的校驗碼 則R和C之間的對應關係如下表: R:0 1 2 3 4 5 6 7 8 9 10 C:1 0 X 9 8 7
	 * 6 5 4 3 2 由此看出 X 就是 10,羅馬數字中的 10 就是X,所以在新標準的身份證號碼中可能含有非數字的字母X。
	 */
	public boolean validateLastNum(String strId) {
		// 判斷身份證是否爲18位
		if (strId.length() != 18) {
			return false;
		}
		// 把String轉換爲StringBuffer是爲了用到reverse()方法
		StringBuffer sb = new StringBuffer(strId);
		// 字符串反轉
		sb.reverse();
		// 轉回來,便於操作
		String id = new String(sb);
		// 如果含有非數字,則直接返回false退出
		try {
			Long.parseLong(id);
		} catch (Exception e) {
			// System.out.println("該字符串只能是數字");
			return false;
		}
		// 下面算法遵照上面的公式
		int sum = 0;
		int C = 0;
		int[] W = new int[17];
		int[] a = new int[17];
		for (int i = 2; i < 19; i++) {
			W[i - 2] = (int) (Math.pow(2, i - 1) % 11);
			a[i - 2] = Integer.parseInt(id.substring(i - 1, i));
			sum += (a[i - 2] * W[i - 2]);
		}
		int R = sum % 11;
		// 將上面得到的結果,根據R:C對應關係,做如下轉換
		if (R == 0) {
			C = 1;
		}
		if (R == 1) {
			C = 0;
		}
		if (R == 2) {
			C = 10;
		}
		if (R > 2) {
			C = 12 - R;
		}
		// 截取第一個字符,即轉換前的最後一個字符
		String lastChar = id.substring(0, 1);
		// 將截取的字符轉換成數字
		int lastNum = Integer.parseInt(lastChar);
		// 判斷身份證的最後個字符和計算得到的數據做比較,如果相等則正確,反之錯誤
		if (lastNum != C) {
			// 由於R=2對應C=10,而10在身份證中用X表示,所以可通過驗證下面兩個條件是否同時滿足來判斷
			if (C == 10 && lastChar.equals("X")) {
				// System.out.println("身份證通過校驗碼驗證");
				return true;
			}
			// System.out.println("身份證未能通過校驗碼驗證");
			return false;
		}
		// System.out.println("身份證通過校驗碼驗證");
		return true;
	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章