shigen
坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 个人IP:shigen
背景
shigen
最近的需要填写各种报名表的场景有点多,很多场景都要输入身份证号。对于这些信息,我特别的敏感,所以,我想着能糊弄过去就糊弄过去。之前也确实有乱填,只要凑够了18位,或者我随意改动身份证上的某一位数字就行了。但是,直到我遇到了一种表单:我改一个数字,它发现了,不让我提交!我气急败坏,我要研究一下这玩意怎么实现的。总不至于调用了某云的身份证地址库吧。
于是一个早晨,我就开始坐在了电脑前,研究起这个了。
申明:测试ID来自于互联网,关键信息我也会进行打码,并无实际的数据价值。
研究
身份证号18位,毋庸置疑。够了18位这是基础,完了就是它的生成规则。我特意的查阅了资料:中华人民共和国居民身份证[1]。

反正就是一套规则约束,最后一位校验码通过运算出来的。
原理懂了,那就要开始写代码验证了。为此,我在互联网上找到了一个身份证号,用于实际的测试验证:

代码设计
身份证号的输入,我选用设计一个通用的组件来完成,实现它的灵活性。
level 0ne
第一层次的,我们不引入任何的算法,只对身份证号的规则进行一次校验,这也是很多网站存在的问题。
分装组件
<template>
<el-form-item :label="label" :prop="prop" :rules="rules">
<el-input v-model="idNumber" @input="checkIdNumber" :placeholder="placeholder" clearable />
</el-form-item>
</template>
<script>
export default {
props: {
label: String,
prop: String,
// 父组件的表单实例
parentFormRef: Object,
placeholder: {
type: String,
default: ''
},
value: {
type: String,
default: ''
}
},
data() {
return {
idNumber: this.value,
rules: [
{
validator: this.validateIdNumber,
trigger: 'blur'
}
]
};
},
watch: {
value(newValue) {
this.idNumber = newValue;
}
},
methods: {
validateIdNumber(rule, value, callback) {
if (!value) {
callback(new Error('请输入身份证号码'));
} else if (!this.check(value)) {
callback(new Error('请输入有效的身份证号码'));
} else {
callback();
}
},
checkIdNumber() {
this.$nextTick(() => {
// 确保在下一次 DOM 更新周期后再访问父组件传递的表单实例
if (this.parentFormRef) {
this.parentFormRef.validateField('idNumber');
}
});
// 将输入的值通过 input 事件传递给父组件
this.$emit('input', this.idNumber);
},
check(value) {
const pattern = /^[1-9]d{5}(18|19|20)?d{2}(0[1-9]|1[0-2])(0[1-9]|[12]d|3[01])d{3}([0-9]|X|x)$/;
return pattern.test(value);
},
}
};
</script>
看起来内容小多,关键的逻辑还是对于身份证号的验证,这里选用的是正则表达式。别的就是一些自定义传值的约束和定义。
设计的时候,踩了很多的坑,具体的注意点写在了注释里。
页面使用
在页面中,我们需要这样使用:
<template>
<div>
<el-form :model="info" ref="myForm">
<id-number-input v-model="info.idNumber" :parentFormRef="myForm" label="身份证号码" prop="idNumber"
placeholder="请输入身份证号码" />
</el-form>
<p>idNumber: {{ info.idNumber }}</p>
<el-button type="primary" @click="submitForm">提交</el-button>
</div>
</template>
<script>
import IdNumberInput from '@/components/IdNumberInput.vue';
export default {
components: {
IdNumberInput
},
data() {
return {
info: {
idNumber: '',
},
myForm: null,
};
},
methods: {
submitForm() {
this.$refs.myForm.validate((valid) => {
if (valid) {
// 表单验证通过,执行提交逻辑
this.$message.success('表单验证通过,执行提交逻辑');
} else {
// 表单验证不通过
this.$message.error('表单验证不通过');
}
});
},
}
};
</script>
如此,简单的第一步完成,看看效果:

修改出生年月日或者后四位数字的任何一位,照样可以现实验证通过。
level Two
在上一步的基础上,引入了新的校验生成规则;参考了文章身份证号规则校验最全总结[2]。
check2(value) {
let idcode = value;
if (!this.check(idcode)) return false;
// 加权因子
const weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 校验码
const checkCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
const code = String(idcode);
const last = idcode[17]// 最后一位
const seventeen = code.substring(0, 17);
// ISO 7064:1983.MOD 11-2 判断最后一位校验码是否正确
const arr = seventeen.split('');
const len = arr.length;
let num = 0;
for (let i = 0; i < len; i++) {
num = num + arr[i] * weightFactor[i];
}
// 获取余数
const resisue = num % 11;
const lastNo = checkCode[resisue];
return last === lastNo;
},
这种方式就是引入了生成规则的校验,这次,随意修改不行了。

以上就是整个探秘+揭秘的整个过程,欢迎评论交流。
与shigen一起,每天不一样!
引用链接
[1]
中华人民共和国居民身份证: https://baike.baidu.com/item/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD%E5%B1%85%E6%B0%91%E8%BA%AB%E4%BB%BD%E8%AF%81/4471408[2]
身份证号规则校验最全总结: https://juejin.cn/post/6925438445871431688
原文始发于微信公众号(shigen):看不惯各种信息收集表,我手写了一个身份证号输入组件
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/270965.html