|
@@ -0,0 +1,193 @@
|
|
|
+package thyyxxk.webserver.utils;
|
|
|
+
|
|
|
+import java.text.ParseException;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.Date;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @description: IdCard functions
|
|
|
+ * @author: DingJie
|
|
|
+ * @create: 2021-04-01 11:42:13
|
|
|
+ **/
|
|
|
+public class IdCardUtil {
|
|
|
+ /**
|
|
|
+ * 每位加权因子
|
|
|
+ * */
|
|
|
+ private static final int[] POWER = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
|
|
|
+ private static final int MAX_LENGTH = 18;
|
|
|
+ private static final int MIN_LENGTH = 15;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证所有的身份证的合法性
|
|
|
+ */
|
|
|
+ public static boolean isValidatedIdCard(String idCard) {
|
|
|
+ if (StringUtil.isBlank(idCard)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (idCard.length() == MIN_LENGTH) {
|
|
|
+ idCard = convertIdCarBy15bit(idCard);
|
|
|
+ }
|
|
|
+ if (StringUtil.isBlank(idCard)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return isValidate18IdCard(idCard);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean isValidate18IdCard(String idCard) {
|
|
|
+ // 非18位为假
|
|
|
+ if (idCard.length() != MAX_LENGTH) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 获取前17位
|
|
|
+ String idCard17 = idCard.substring(0, 17);
|
|
|
+ // 获取第18位
|
|
|
+ String idCard18Code = idCard.substring(17, 18);
|
|
|
+ char[] c;
|
|
|
+ String checkCode;
|
|
|
+ // 是否都为数字
|
|
|
+ if (isDigital(idCard17)) {
|
|
|
+ c = idCard17.toCharArray();
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ int[] bit;
|
|
|
+ bit = convertCharToInt(c);
|
|
|
+ int sum17;
|
|
|
+ sum17 = getPowerSum(bit);
|
|
|
+ // 将和值与11取模得到余数进行校验码判断
|
|
|
+ checkCode = getCheckCodeBySum(sum17);
|
|
|
+ if (null == checkCode) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 将身份证的第18位与算出来的校码进行匹配,不相等就为假
|
|
|
+ return idCard18Code.equalsIgnoreCase(checkCode);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将15位的身份证转成18位身份证
|
|
|
+ */
|
|
|
+ private static String convertIdCarBy15bit(String idCard) {
|
|
|
+ String idCard17;
|
|
|
+ // 非15位身份证
|
|
|
+ if (idCard.length() != MIN_LENGTH) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (isDigital(idCard)) {
|
|
|
+ // 获取出生年月日
|
|
|
+ String birthday = idCard.substring(6, 12);
|
|
|
+ Date birthdate = null;
|
|
|
+ try {
|
|
|
+ birthdate = new SimpleDateFormat("yyMMdd").parse(birthday);
|
|
|
+ } catch (ParseException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ if (null == birthdate) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Calendar cday = Calendar.getInstance();
|
|
|
+ cday.setTime(birthdate);
|
|
|
+ String year = String.valueOf(cday.get(Calendar.YEAR));
|
|
|
+ idCard17 = idCard.substring(0, 6) + year + idCard.substring(8);
|
|
|
+ char[] c = idCard17.toCharArray();
|
|
|
+ String checkCode;
|
|
|
+ int[] bit;
|
|
|
+ // 将字符数组转为整型数组
|
|
|
+ bit = convertCharToInt(c);
|
|
|
+ int sum17;
|
|
|
+ sum17 = getPowerSum(bit);
|
|
|
+ // 获取和值与11取模得到余数进行校验码
|
|
|
+ checkCode = getCheckCodeBySum(sum17);
|
|
|
+ // 获取不到校验位
|
|
|
+ if (null == checkCode) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 将前17位与第18位校验码拼接
|
|
|
+ idCard17 += checkCode;
|
|
|
+ } else { // 身份证包含数字
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return idCard17;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数字验证
|
|
|
+ */
|
|
|
+ private static boolean isDigital(String str) {
|
|
|
+ return str != null && !"".equals(str) && str.matches("^[0-9]*$");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将身份证的每位和对应位的加权因子相乘之后,再得到和值
|
|
|
+ */
|
|
|
+ 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取模得到余数进行校验码判断
|
|
|
+ */
|
|
|
+ private static String getCheckCodeBySum(int sum17) {
|
|
|
+ String checkCode;
|
|
|
+ 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:
|
|
|
+ default:
|
|
|
+ checkCode = "1";
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return checkCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将字符数组转为整型数组
|
|
|
+ */
|
|
|
+ private static int[] convertCharToInt(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;
|
|
|
+ }
|
|
|
+}
|