题目:在线验证18位身份证
1.概述
很多网站的注册功能中,都需要用户输入身份证号码。而普通的数据验证不能准确的判断用户输入的身份证号码的合法性。也就是说不能按照居民身份证的特征对其进行验证。居民身份证是由17位数字本体码和1位数字校验码组成的。分别为6位数字地址码、8位数字出生日期码,3位数字顺序码和1位数字校验码。本实例实现“网络购物商城”的用户注册程序,用户的身份号根据居民身份证的特征进行验证。注意,格式正确的身份证号码不一定是真实存在的,而格式不正确的身份证号码一定不是真实存在的。
2.技术要点
居民身份证是由地区码、出生日期码、顺序码以及一位校验码组成。第一、二位数字表示公民所在的省份(或自治区),第3、4位表示公民所在地的市(或州),第5、6位表示公民所在地的县(或县级市)。按GB/T 2260的规定执行。第7位至第14位表示公民的出生日期码表示居民出生的年、月、日,年、月、日代码之间不用分隔符。例如某公民的出生日期是1984年11月3日,其出生日期码为19841103。按GB/T 7408的规定执行。顺序码表示在同一地区码所标识的范围内,对同年、同月、同日出生的人规定的顺序号,奇数分配给男性,偶数分配给女性。校验码采用ISO 7064:1983,MOD 11-2校验码系统。
关键技术在于计算校验码。公式为:
∑(ai * wi)(mod 11)
对ai * wi相加的结果对11取模。
i:表示身份证号码从右至左包括校验码在内的位置序号。
ai:表示第i位置上的号码字符值。例如某人的身份证号码为“220183********2626”(*号部分代表出生日期号码)。则ai代表“2、2、0、1、8、3、*、*、*、*、*、*、*、*、2、6、2、6”。
wi:表示I位置上的加权因子,加权因子的值从第1位到第17位分别为“7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2”。
通过对∑(ai * wi)计算结果对11取模获取校验码,如果余数为0,则获取的校验码为1;余数为1,则校验码为0。对应关系为(0,1)、(1,0)、(2,X)、(3,9)、(4,8)、(5,7)、(6,6)、(7,5)、(8,4)、(9,3)、(10,2)。
注意:对于15位身份证的验证,要先将其扩展18位。需要将出生日期码扩展为4位。也就是在出生日期前加一个“19”。
3.开发步骤
(1)创建index.jsp页面。在该页面中添加如表1所示的表单元素。
表1 index.jsp页面的表单元素
元素类型 |
元素名称 |
属性设置 |
说 明 |
form1 |
action="ValidateServlet" onsubmit="return Mycheck()" |
表单元素 |
|
user_name |
size=”18” |
文本框标签 |
|
user_password |
size=”20” |
密码标记 |
|
user_affirm |
size=”20” |
密码标记 |
|
user_brithday |
size=”18” |
文本框标签 |
|
user_card |
size=”18” |
文本框标签 |
|
user_email |
Size=”18” |
文本框标签 |
|
select |
<option value="男">男</option> <option value="女">女</option> |
列表标记 |
(2)本实例中首先通过用户输入的生日与身份证号进行验证,如果身份证号码中的第7位与第14位出生日期号码,与用户在index.jsp页面中输入的出生日期不符的话,则验证失败。不用对校验码进行验证。在index.jsp页面中通过Java Script脚本对用户输入的出生日期与身份证号码进行验证,具体代码如下:
<script language="javascript">
function Mycheck()
{
if (form1.user_brithday.value=="") <!--判断是否输入出生日期-->
{ alert("请输入出生日期!");
form1.user_brithday.focus(); <!--将焦点定位到出生日期文本框-->
return false; <!--返回-->
}
if(form1.user_brithday.value.length!=10) <!--判断用户输入的出生日期长度是否为10-->
{
alert("您输入的日期不对!请输入标准日期(如:2004-07-27)"); <!--提示信息-->
form1.user_brithday.focus(); <!--将焦点定位到出生日期文本框-->
return false;
}
if(form1.user_brithday.value.indexOf('-',0)==-1) <!--判断用户输入的出生日期中是否包含符号“-”-->
{alert("您输入的日期不对!请输入标准日期(如:2004-07-27)");
form1.user_brithday.focus(); <!--将焦点定位到出生日期文本框-->
return false; <!--返回-->
}
if(form1.user_brithday.value.substr(4,1)!="-") <!--判断用户输入的出生日期的年份后是否有符号“-”-->
{alert("您输入的日期不对!请输入标准日期(如:2004-07-27)");
form1.user_brithday.focus();
return false;
}
if(form1.user_brithday.value.substr(7,1)!="-") <!--判断用户输入的出生日期中的月份后是否有符号“-”-->
{alert("您输入的日期不对!请输入标准日期(如:2004-07-27)");
form1.user_brithday.focus();
return false;
}
if(form1.user_card.value == ""){ <!--判断用户是否输入身份证号-->
alert("请输入身份证号码");
form1.user_card.focus();
return false;
}
if((form1.user_card.value.length != 15)&&(form1.user_card.value.length != 18)){
<!--判断用户输入的身份证的长度是否正确-->
alert("输入的身份证号码不正确");
return false;
}
}
</script>
(3)创建类IdcardValidate,该类中包含有验证身份证格式方法,首先在该类中创建int型变量weightNumber与checknumber分别代表加权因子与校验吗。代码如下:
public class IdcardValidate {
private final int[] weightNumber = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1};
private final int[] checknumber = new int[]{1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2};
}
(4)编写validayBrithday()方法判断用户输入的出生日期与用户输入的身份证号码中出生日期号是否相等。该方法有两个String类型的参数,分别代表用户输入的出生日期与身份证号码,代码如下:
public boolean validayBrithday(String idcard, String brithday) {
String sunidcard = idcard.substring(6, 14); //获取用户输入的身份证号码中的出生日期码
if (sunidcard.equals(brithday)) { //判断用户输入的出生日期与身份证号码中的出生日期码是否相等
return true;
}
return false;
}
(5)编写计算18位效验码方法getCheckDigit(),该方法包含有一个String类型参数,指定要进行验证的身份证号码,如果值为身份证号码中的校验码值,具体代码如下:
private String getCheckDigit(String cardNumber) {
int verify = 0;
cardNumber = cardNumber.substring(0, 17); //获取身份证号码中的前17位
int sum = 0;
int[] wi = new int[17]; //创建int型数组
for (int i = 0; i < 17; i++) { //循环向数组赋值
String strid = cardNumber.substring(i, i + 1);
wi[i] = Integer.parseInt(strid);
}
for (int i = 0; i < 17; i++) { //循环遍历数组
sum = sum + weightNumber[i] * wi[i]; //对17位本利码加权求和
}
verify = sum % 11; //取模
if (verify == 2) { //如果模为2,则返回“X”
return "X";
} else {
return String.valueOf(checknumber[verify]); //否则返回对应的校验码
}
}
(6)编写将15位身份证转换为18位身份证号码方法fiveteenToeighteen(),该方法有一个String类型的参数,指定15位身份证,返回值为18位身份证。具体代码如下:
public String fiveteenToeighteen(String fifteenNumber) {
String eighteenNumberBefore = fifteenNumber.substring(0, 6); //获取参数身份证号码中的地区码
String eightNumberAfter = fifteenNumber.substring(6, 15); //获取参数身份证号码中的出生日期码
String eighteenNumber;
eighteenNumber = eighteenNumberBefore + "19"; //将地区码后面加“19”
eighteenNumber = eighteenNumber + eightNumberAfter; //获取地区码加出生日期码
eighteenNumber = eighteenNumber + this.getCheckDigit(eighteenNumber); //获取该身份证的校验码
return eighteenNumber; //将转换后的身份证号码返回
}
(7)编写方法verify(),该方法判断指定身份证格式是否正确,如果验证成功则返回“身份证验证成功”,如果验证失败则返回“验证失败”。具体代码如下:
public String verify(String cardNumber) {
String str = "身份证验证成功";
if (cardNumber.length() == 15) { //如果要进行验证的身份证号码为15位
cardNumber = this.fiveteenToeighteen(cardNumber); //将其转换为18位
}
if (cardNumber.length() != 18) {
return "验证失败";
}
String checkDight = cardNumber.substring(17, 18); //获取要进行验证身份证号码的校验号
if (checkDight.equals(this.getCheckDigit(cardNumber))) { //判断校验码是否正确
return str;
}
return "验证失败";
}
(8)当用户添加完注册信息会,系统将提交URL地址为ValidateServlet的Servlet。在该Servlet中,调用验证18位身份证号码方法,具体代码如下:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
IdcardValidate validate = new IdcardValidate(); //创建保存身份证验证类对象
String brithday = request.getParameter("user_brithday"); //获取用户输入生日
String idCard = request.getParameter("user_card"); //获取用户输入身份证号码
String message = "身份证格式不正确";
String brithdaySub = brithday.replace("-",""); //字符串替换
boolean bool = validate.validayBrithday(idCard, brithdaySub);
//调用判断用户输入的出生日期是否与身份证号码中的出生日期码相等
if(bool == false){
request.getSession().setAttribute("message", message); //将信息保存在session对象中
response.sendRedirect("index.jsp"); //请求转发地址
return;
}
else if(bool == true){
String messageId = validate.verify(idCard); //调用验证身份证号码方法
request.getSession().setAttribute("message",messageId); //将提示信息保存在session对象中
response.sendRedirect("index.jsp");
return;
}
}