大陆居民身份证验证方法(java)
1、设置接口
@Constraint(validatedBy = ChineseIdNumberValidator.class)
@Target({ElementType.METHOD,
ElementType.FIELD,
ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IdNumber { String message() default "{common.IdNumber.Pattern}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};
}
2、编写Validator
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger; import javax.validation.ConstraintValidatorContext; /**
*
* <p>
* 判断18位身份证的合法性
* </p>
* 根据〖中华人民共和国国家标准GB11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。
* 排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
* <p>
* 顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同 日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配 给女性。
* </p>
* <p>
* 1.前1、2位数字表示:所在省份的代码; 2.第3、4位数字表示:所在城市的代码; 3.第5、6位数字表示:所在区县的代码;
* 4.第7~14位数字表示:出生年、月、日; 5.第15、16位数字表示:所在地的派出所的代码; 6.第17位数字表示性别:奇数表示男性,偶数表示女性;
* 7.第18位数字是校检码:也有的说是个人信息码,一般是随计算机的随机产生,用来检验身份证的正确性。校检码可以是0~9的数字,有时也用x表示。
* </p>
* <p>
* 第十八位数字(校验码)的计算方法为: 1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1
* 6 3 7 9 10 5 8 4 2
* </p>
* <p>
* 2.将这17位数字和系数相乘的结果相加。
* </p>
* <p>
* 3.用加出来和除以11,看余数是多少?
* </p>
* 4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
* <p>
* 5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
* </p>
*
* <p>
* 对于15位身份证,不需要判断最后一位验证码,最后一位代表性别,奇数表示男性,偶数表示女性 默认使用18位身份证号,15位也支持
* </p>
*
* @author rooseek
*
*
*/
public class ChineseIdNumberValidator implements ConstraintValidator { private final static Map<String, String> code2Province = new HashMap<String, String>() { private static final long serialVersionUID = 1L; {
this.put("11", "北京");
this.put("12", "天津");
this.put("13", "河北");
this.put("14", "山西");
this.put("15", "内蒙古");
this.put("21", "辽宁");
this.put("22", "吉林");
this.put("23", "黑龙江");
this.put("31", "上海");
this.put("32", "江苏");
this.put("33", "浙江");
this.put("34", "安徽");
this.put("35", "福建");
this.put("36", "江西");
this.put("37", "山东");
this.put("41", "河南");
this.put("42", "湖北");
this.put("43", "湖南");
this.put("44", "广东");
this.put("45", "广西");
this.put("46", "海南");
this.put("50", "重庆");
this.put("51", "四川");
this.put("52", "贵州");
this.put("53", "云南");
this.put("54", "西藏");
this.put("61", "陕西");
this.put("62", "甘肃");
this.put("63", "青海");
this.put("64", "宁夏");
this.put("65", "新疆");
}
}; private static final int weightFactor[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; private static final String checkCode[] = {"1", "0", "X", "9", "8", "7", "6", "5",
"4", "3", "2"}; private static final GregorianCalendar calendar = (GregorianCalendar) GregorianCalendar.getInstance(); @Override
public void initialize(IdNumber constraintAnnotation) {
} @Override
public boolean isValid(String idNumber, ConstraintValidatorContext context) {
if (idNumber == null) {
return true;
} return isValid(idNumber);
} protected boolean isValid(String idNumber) {
if (idNumber == null) {
return true;
} if (idNumber.length() == 15) {
return isValid15(idNumber);
} else if (idNumber.length() == 18) {
return isValid18(idNumber);
} return false;
} private boolean isValid15(String idNumber) {
if (idNumber == null || idNumber.length() != 15) {
return false;
} if (!isDigital(idNumber)) {
return false;
} //check province code
String province = idNumber.substring(0, 2);
if (!code2Province.containsKey(province)) {
return false;
} //check birthday
String birthday = idNumber.substring(6, 12);
int month = Integer.parseInt(idNumber.substring(8, 10));
int day = Integer.parseInt(idNumber.substring(10, 12)); //check birthday format and whether this date is before current time
Date birthDate = null;
try {
birthDate = new SimpleDateFormat("yyMMdd").parse(birthday);
} catch (ParseException ex) {
Logger.getLogger(ChineseIdNumberValidator.class.getName()).log(Level.SEVERE, null, ex);
}
if (birthDate == null || System.currentTimeMillis() <= birthDate.getTime()) {
return false;
} //check year, month, day
calendar.setTime(birthDate);
if (calendar.get(Calendar.YEAR) < IdNumberConstant.MIN_YEAR) {
return false;
} if (month < 1 || month > 12) {
return false;
}
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day < 1 || day > 31) {
return false;
}
case 4:
case 6:
case 9:
case 11:
if (day < 1 || day > 30) {
return false;
}
case 2:
if (calendar.isLeapYear(calendar.get(Calendar.YEAR))) {
if (day < 1 || day > 29) {
return false;
}
} else {
if (day < 1 || day > 28) {
return false;
}
}
} return true;
} private boolean isValid18(String idNumber) {
if (idNumber == null || idNumber.length() != 18) {
return false;
} String idNumber17 = idNumber.substring(0, 17);
String idNumber18Code = idNumber.substring(17, 18);
char charArray[]; //check prefix 17 numbers are all digital
if (isDigital(idNumber17)) {
charArray = idNumber17.toCharArray();
} else {
return false;
} //check region code
String province = idNumber.substring(0, 2);
if (!code2Province.containsKey(province)) {
return false;
} //check birthday
String birthday = idNumber.substring(6, 14);
int year = Integer.parseInt(idNumber.substring(6, 10));
int month = Integer.parseInt(idNumber.substring(10, 12));
int day = Integer.parseInt(idNumber.substring(12, 14)); //check birthday format and whether this date is before current time
Date birthDate = null;
try {
birthDate = new SimpleDateFormat("yyyyMMdd").parse(birthday);
} catch (ParseException ex) {
Logger.getLogger(ChineseIdNumberValidator.class.getName()).log(Level.SEVERE, null, ex);
}
if (birthDate == null || System.currentTimeMillis() <= birthDate.getTime()) {
return false;
} //check year, month, day
if (year < IdNumberConstant.MIN_YEAR) {
return false;
} if (month < 1 || month > 12) {
return false;
}
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day < 1 || day > 31) {
return false;
}
break;
case 4:
case 6:
case 9:
case 11:
if (day < 1 || day > 30) {
return false;
}
break;
case 2:
if (isLeapYear(year)) {
if (day < 1 || day > 29) {
return false;
}
} else {
if (day < 1 || day > 28) {
return false;
}
}
break;
} //check the sum of prefix 17 numbers mutilplied by weighted factor equals the last check code
if (null != charArray) {
if (!idNumber18Code.equals(
getCheckCode(
getPowerSum(
char2Int(charArray))))) {
return false;
} } return true;
} @SuppressWarnings("unused")
private String convert15To18(String idNumber) {
if (idNumber.length() != 15) {
return null;
} String idNumber17;
if (isDigital(idNumber)) {
String birthday = idNumber.substring(6, 12);
Date birthdate = null;
try {
birthdate = new SimpleDateFormat("yyMMdd").parse(birthday);
} catch (ParseException ex) {
Logger.getLogger(ChineseIdNumberValidator.class.getName()).log(Level.SEVERE, null, ex);
} calendar.setTime(birthdate);
String year = String.valueOf(calendar.get(Calendar.YEAR));
idNumber17 = idNumber.substring(0, 6) + year + idNumber.substring(8);
char charArray[] = idNumber17.toCharArray();
if (null != charArray) {
int sum17 = getPowerSum(char2Int(charArray));
idNumber17 += getCheckCode(sum17);
}
} else {
return null;
}
return idNumber17;
} private boolean isDigital(String str) {
return str == null || "".equals(str) ? false : str.matches("[0-9]*");
} private int getPowerSum(int[] bit) {
int sum = 0;
if (weightFactor.length != bit.length) {
return sum;
}
for (int i = 0; i < bit.length; i++) {
sum = sum + bit[i] * weightFactor[i];
}
return sum;
} private String getCheckCode(int sum17) {
return checkCode[sum17 % 11];
} private int[] char2Int(char[] charArray) throws NumberFormatException {
int[] array = new int[charArray.length];
int k = 0;
for (char temp : charArray) {
array[k++] = Integer.parseInt(String.valueOf(temp));
}
return array;
} @SuppressWarnings("unused")
private boolean isValidIdRegion(String region) {
if (!Regions.isValidRegion(region)) {
return false;
} //idNumber start with something like "110000 北京市/110100 市辖区/110200 县" is not valid
if (region.substring(4, 6).equals(IdNumberConstant.CITY_SUFFIX)) {
return false;
} //台湾 香港 澳门暂时屏蔽
String province = region.substring(0, 2);
if (!isValidProvince(province)) {
return false;
} return true;
} private boolean isValidProvince(String province) {
return !(province.equals(IdNumberConstant.TAIWANG)
|| province.equals(IdNumberConstant.HONGKONG)
|| province.equals(IdNumberConstant.MACAU));
} private boolean isLeapYear(int year) {
return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
}
}
大陆居民身份证验证方法(java)的更多相关文章
- 18位身份证验证(Java)加入身份证输入验证是否满足18位代码(修订稿)
		package day20181016; /** * 身份证的验证 34052419800101001X * */ import java.util.Scanner; public class Zuo ... 
- 18位身份证验证(Java)
		我的代码: package day20181016;/** * 身份证的验证 34052419800101001X * */import java.util.Scanner;public class ... 
- Java连接MySQL数据库实现用户名密码的验证方法 Java语句中sql查询语句'' ""作用
		//方法一,可以验证登录,但方法不实用.package com.swift; import java.sql.Connection; import java.sql.DriverManager; im ... 
- 【NumberValidators】大陆身份证验证
		需要说明的是这里的大陆身份证识别并不是公安局联网的识别,而是按国标GB 11643进行的验证,所以其验证结果只能说符合国标规范,但不能保证该身份证一定真实存在,如果你实际需求是希望身份证一定真实存在, ... 
- java身份证验证
		import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ... 
- java对身份证验证及正则表达式解析
		原文地址:http://www.cnblogs.com/zhongshengzhen/ java对身份证验证及正则表达式解析 package service; import java.text.Par ... 
- java 常用的验证方法帮助类
		import java.text.ParseException; import java.util.Collection; import java.util.Map; /** * 常用的验证方法帮助类 ... 
- Java国际化号码验证方法,国内手机号正则表达式
		Java国际化号码验证方法,国内手机号正则表达式 中国电信号段 133.149.153.173.177.180.181.189.199 中国联通号段 130.131.132.145.155.156.1 ... 
- Java基础之身份证验证
		//简约版package test; import java.util.Scanner; public class ID { /** * 匹配算法 : 1) 得到17位身份证号码与下面给出的17位 2 ... 
随机推荐
- [King.yue]Ext中Grid得到选择行数据的方法总结
			(1)grid.getStore().getRange(0,store.getCount()); //得到grid所有的行 (2)grid.getSelectionModel().getSele ... 
- 仿酷狗音乐播放器开发日志三——修复CEditUI的bug2
			无意中发现了CEditUI控件的另一个bug,当我给播放器的搜索栏获取焦点时,这时再改变窗体大小,原本搜索栏应该对应着也改变大小,却发现CEditUI内嵌的edit控件没有跟着改变(如下图),跟着调试 ... 
- SELinux的故障排除一例
			刚刚采用Puppet部署了dokuwiki,不过配置完成后报错: DokuWiki Setup Error The datadir ('pages') at /pages is not found, ... 
- opencv 在工业中的应用:模板匹配
			模板匹配在工业中经常有两个用途,一模板匹配进行产品定位,二根据匹配度来判断是OK的产品还是NG的产品.我用OPENCV做了个模板匹配定位的DEMO. (1)点击打开图像按钮打开一幅图像 (2)点击定义 ... 
- TCP服务端和客户端的框架
			提供一个框架服务器端: 创建一个Socket sFd=socket(AF_INET,SOCK_STREAM,0) 把Socket和本机的IP,TCP口绑定 bind(sFd,(structsockad ... 
- MySQL 字段类型详解
			一.非数字类型 类型 范围 说明 Char(N) [ binary] N=1~255 个字元 binary :分辨大小写 固定长度 std_name cahr(32) not null VarCh ... 
- SRM 596 DIV 2
			前段时间终于配置好了TopCoder的环境,所以就拿这场的DIV2练习了一下 1. 250pt FoxAndSightseeing 题意 给你n个城市的位置,他们在同一直线上,要求你跳过其中某一个城市 ... 
- 初页CTO丁乐:分布式以后还能敏捷吗? - 极客头条 - CSDN.NET
			初页CTO丁乐:分布式以后还能敏捷吗? - 极客头条 - CSDN.NET 
- TCP/IP协议详解内容总结
			TCP/IP协议 TCP/IP不是一个协议,而是一个协议族的统称.里面包括IP协议.IMCP协议.TCP协议. TCP/IP分层: 这里有几个需要注意的知识点: 互联网地址:也就是IP地址,一般为 ... 
- Java中HashMap和TreeMap的区别深入理解
			首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对. Has ... 
