vue3+ts+element-plus密码强弱校验+密码自定义规则校验

本文详细介绍了前端密码强度校验的实现过程,包括密码长度、字母、数字、符号的规则以及禁止包含用户名、3个及以上相同或连续字符、键盘连续字符等条件。同时展示了使用Vue.js和Element-Plus组件库构建的密码强度条,通过不同颜色和长度的进度条实时反馈密码强度。此外,还提供了TypeScript实现的密码规则校验函数,包括正则表达式和键盘字符表,确保密码符合复杂性要求。
摘要由CSDN通过智能技术生成

一、效果描述和结果展示:

  • 密码强弱 校验是根据以下四种规则来判断划分的5个等级。
    • 长度
    • 字母
    • 数字
    • 符号
  • 密码规则 校验是根据以下四种规则来进行校验。
    • 是否包含用户名;
    • 是否包含3个及以上相同或连续的字符;
    • 是否包含3个及以上键盘连续字符;(横向、斜向都包括)
    • 数字、小写字母、大写字母、特殊字符,至少包含两种

结果展示:

  • 密码长度小于8 位

  • 密码包含用户名

 

  •  密码包含3个相同或者连续的字符

 

  •  包含3个及以上键盘连续字符;(横向、斜向都包括)

 

  •  密码不满足数字、小写字母、大写字母、特殊字符,至少包含两种

 

  •  各项密码强度展示

 

 

 

 

  

 

二、静态页面:

<el-form
     :model="registerData"
     label-width="100px"
     :rules="rules"
     ref="ruleFormRef">
    <el-form-item label="密码" prop="password">
       <el-input v-model="registerData.password" placeholder="请输入密码" />
    </el-form-item>
    <el-form-item
        v-if="registerData.password !== '' && registerData.password !== undefined"
        label=""
        align="center"
        style="height: 25px">
      <!-- 展示长度条 -->
       <div
           class="bar"
           v-if="registerData.password !== '' && registerData.password !== undefined"
           :style="{ background: barColor, width: width + '%' }">
        <!-- 展示文字 -->
          <div
              class="strength"
              :style="{ color: barColor }"
              v-if="registerData.password !== '' && registerData.password !== undefined">
          {{ strength }}
          </div>
        </div>
     </el-form-item>
</el-form>

三、css部分:

.strength {
    font-size: 13px;
    color: #271E25;
    position: relative;
    top: 5px;
    left: 0;
    transition: 0.5s all ease;
  }  
.bar {
    /* width: 400px; */
    height: 5px;
    background: red;
    transition: 0.5s all ease;
    max-width: 420px;
    margin: 2px 0 5px 5px;
    position: absolute;
  }

四、ts部分:

import { ref, watch, reactive } from 'vue';
import type { FormInstance } from 'element-plus';
// 引入验证方法
import { checkPasswordRule, level } from './CheckPassword';

// 强度条颜色
const barColor = ref('');
// 强度条长度
const width = ref('');
// 强度条说明
const strength = ref('');

const ruleFormRef = ref<FormInstance>();
// 注册表单校验规则
  const rules = reactive({
    password: [{ validator: validatePassword, trigger: 'blur' }]
  });
// 注册数据
  const registerData = reactive({
    password: '',
  });
// 监听注册页面的新密码变化状态,来改变密码强弱显示
  watch(
    () => registerData.password,
    (newVal) => {
      if (newVal != '') {
        const res: string = level(newVal);
        if (res == '非常弱') {
          barColor.value = 'red';
          width.value = '20';
          strength.value = '非常弱';
        } else if (res == '弱') {
          barColor.value = '#ee795c';
          width.value = '40';
          strength.value = '弱';
        } else if (res == '一般') {
          barColor.value = 'orange';
          width.value = '60';
          strength.value = '一般';
        } else if (res == '强') {
          barColor.value = 'green';
          width.value = '80';
          strength.value = '强';
        } else if (res == '非常强') {
          barColor.value = '#1B8EF8';
          width.value = '100';
          strength.value = '非常强';
        }
      }
    }
  );

// 密码校验规则
  const validatePassword = (rule: any, value: string, callback: any) => {
    if (value === '') {
      callback(new Error('请输入密码'));
    } else {
      let name: string = '';
      if (registerData.username === '') {
        name = '空';
      } else {
        name = registerData.username;
      }
      const result: string = checkPasswordRule(value, name);
      if (result === '校验通过') {
        callback();
      } else {
        callback(new Error(result));
      }
    }
  };

// 提交校验方法
  const submitForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return;
    formEl.validate((valid) => {
      if (valid) {
        console.log('submit!');
        ElMessage({
            message: '注册成功!',
            type: 'success'
        });
      } else {
        console.log('error submit!');
        return false;
      }
    });
  };

五、强弱校验、规则校验 CheckPassword.ts:

    /**
     * 数字
     */
    const REG_NUMBER:string  = ".*\\d+.*";
    /**
     * 小写字母
     */
    const REG_UPPERCASE:string = ".*[A-Z]+.*";
    /**
     * 大写字母
     */
    const REG_LOWERCASE:string = ".*[a-z]+.*";
    /**
     * 特殊符号(~!@#$%^&*()_+|<>,.?/:;'[]{}\)
     */
    const REG_SYMBOL:string = ".*[~!@#$%^&*()_+|<>,.?/:;'\\[\\]{}\"]+.*";
    /**
     * 键盘字符表(小写)
     * 非shift键盘字符表
     */
    const CHAR_TABLE1:string[][] = [
            ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\0'],
            ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\'],
            ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '\0', '\0'],
            ['z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '\0', '\0']];
    /**
     * shift键盘的字符表
     */
    const CHAR_TABLE2:string[][] = [
            ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\0'],
            ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '{', '}', '|'],
            ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ':', '"', '\0', '\0'],
    ['z', 'x', 'c', 'v', 'b', 'n', 'm', '<', '>', '?', '\0', '\0', '\0']];
            
    /**
     * 校验密码是否符合条件
     * @param password 密码
     * @param username 用户名
     */
export const checkPasswordRule = (password:string,username:string) => { 
    if (password === '' || password.length < 8 || password.length > 32) { 
        // console.log("长度小于8,或大于32");
        return "密码长度应大于8小于32";
    } if (password.indexOf(username) !== -1) { 
        // console.log("包含用户名");
        return "请勿包含用户名";
    }
    if (isContinuousChar(password)) {
        // console.log("包含3个及以上相同或字典连续字符");
        return "请勿包含3个及以上相同或连续的字符";
    }
    if (isKeyBoardContinuousChar(password)) {
        // console.log("包含3个及以上键盘连续字符");
        return "请勿包含3个及以上键盘连续字符";
    }
    let i:number = 0;
    if (password.match(REG_NUMBER)) i++;
    if (password.match(REG_LOWERCASE)) i++;
    if (password.match(REG_UPPERCASE)) i++;
    if (password.match(REG_SYMBOL)) i++;
    if (i < 2) {
        // console.log(("数字、小写字母、大写字母、特殊字符,至少包含两种"));
        return "数字、小写字母、大写字母、特殊字符,至少包含两种";
    }
    // console.log(i);
    return "校验通过";
}

    /**
     * 是否包含3个及以上相同或字典连续字符
     */
const isContinuousChar = (password:string) => { 
    let chars: string[] = password.split('')
    let charCode: number[] = [];
    for (let i = 0; i < chars.length - 2; i++) {
        charCode[i] = chars[i].charCodeAt(0)
    }
    for (let i = 0; i < charCode.length - 2; i++) {
        let n1 = charCode[i];
        let n2 = charCode[i + 1];
        let n3 = charCode[i + 2];
        // 判断重复字符
        if (n1 == n2 && n1 == n3) {
            return true;
        }
        // 判断连续字符: 正序 + 倒序
        if ((n1 + 1 == n2 && n1 + 2 == n3) || (n1 - 1 == n2 && n1 - 2 == n3)) {
            return true;
        }
    }
    return false;
}
    /**
     * 是否包含3个及以上键盘连续字符
     * @param password 待匹配的字符串
     */
    const isKeyBoardContinuousChar = (password:string) => { 
        if (password === '') {
            return false;
        }
        //考虑大小写,都转换成小写字母
        let lpStrChars: string[] = password.toLowerCase().split('')
        // 获取字符串长度
        let nStrLen: number = lpStrChars.length;
        // 定义位置数组:row - 行,col - column 列
        const pRowCharPos:number[] = new Array(nStrLen).fill('')
        const pColCharPos: number[] = new Array(nStrLen).fill('')
        for (let i = 0; i < nStrLen; i++) {
            let chLower: string = lpStrChars[i];
            pColCharPos[i] = -1;
            // 检索在表1中的位置,构建位置数组
            for (let nRowTable1Idx = 0; nRowTable1Idx < 4; nRowTable1Idx++) {
                for (let nColTable1Idx = 0; nColTable1Idx < 13; nColTable1Idx++) {
                    if (chLower == CHAR_TABLE1[nRowTable1Idx][nColTable1Idx]) {
                        pRowCharPos[i] = nRowTable1Idx;
                        pColCharPos[i] = nColTable1Idx;
                    }
                }
            }
            // 在表1中没找到,到表二中去找,找到则continue
            if (pColCharPos[i] >= 0) {
                continue;
            }
            // 检索在表2中的位置,构建位置数组
            for (let nRowTable2Idx = 0; nRowTable2Idx < 4; nRowTable2Idx++) {
                for (let nColTable2Idx = 0; nColTable2Idx < 13; nColTable2Idx++) {
                    if (chLower == CHAR_TABLE2[nRowTable2Idx][nColTable2Idx]) {
                        pRowCharPos[i] = nRowTable2Idx;
                        pColCharPos[i] = nColTable2Idx;
                    }
                }
            }
        }
       // 匹配坐标连线
        for (let j = 1; j <= nStrLen - 2; j++) {
            //同一行
            if (pRowCharPos[j - 1] == pRowCharPos[j] && pRowCharPos[j] == pRowCharPos[j + 1]) {
                // 键盘行正向连续(asd)或者键盘行反向连续(dsa)
                if ((pColCharPos[j - 1] + 1 == pColCharPos[j] && pColCharPos[j] + 1 == pColCharPos[j + 1]) ||
                        (pColCharPos[j + 1] + 1 == pColCharPos[j] && pColCharPos[j] + 1 == pColCharPos[j - 1])) {
                    return true;
                }
            }
            //同一列
            if (pColCharPos[j - 1] == pColCharPos[j] && pColCharPos[j] == pColCharPos[j + 1]) {
                //键盘列连续(qaz)或者键盘列反向连续(zaq)
                if ((pRowCharPos[j - 1] + 1 == pRowCharPos[j] && pRowCharPos[j] + 1 == pRowCharPos[j + 1]) ||
                        (pRowCharPos[j - 1] - 1 == pRowCharPos[j] && pRowCharPos[j] - 1 == pRowCharPos[j + 1])) {
                    return true;
                }
            }
        }
        return false;
}


/**
 * 密码强度校验
 */
/**
 * 长度
 * @param str 
 */
const length = (str:string) => { 
    if(str.length<5){ 
        return 5;
    }else if(str.length<8){
        return 10;
    }else{
        return 25;
    }
}
/**
 * 字母
 * @param str 
 */
const letters = (str: string) => { 
    let count1=0,count2=0;
    for(let i=0;i<str.length;i++){
        if(str.charAt(i)>='a'&&str.charAt(i)<='z'){
            count1++;
        }
        if(str.charAt(i)>='A'&&str.charAt(i)<='Z'){
            count2++;
        }
    }
    if(count1==0 && count2==0){
        return 0;
    }
    if(count1!=0 && count2!=0){
        return 20;
    }
    return 10;
}

/**
 * 数字
 * @param str 
 */
const numbers = (str: string) => { 
    let count=0;
    for(let i=0;i<str.length;i++){
        if(str.charAt(i)>='0'&&str.charAt(i)<='9'){
            count++;
        }
    }
    if(count==0){
        return 0;
    }
    if(count==1){
        return 10;
    }
    return 20;  
}
/**
 * 符号
 * @param str 
 */
const symbols = (str: string) => { 
    let count=0;
    for(let i=0;i<str.length;i++){
        if(str.charCodeAt(i)>=0x21 && str.charCodeAt(i)<=0x2F ||
                str.charCodeAt(i)>=0x3A && str.charCodeAt(i)<=0x40 ||
                str.charCodeAt(i)>=0x5B && str.charCodeAt(i)<=0x60 ||
                str.charCodeAt(i)>=0x7B && str.charCodeAt(i)<=0x7E ){
            count++;
        }
    }
    if(count==0){
        return 0;
    }
    if(count==1){
        return 10;
    }
    return 25;
}
/**
 * 得分机制
 * @param str 
 */
const rewards = (str: string) => {
    let letter=letters(str);//字母
    let number=numbers(str);//数字
    let symbol=symbols(str);//符号
    if(letter>0 && number>0 && symbol==0){//字母和数字
        return 2;
    }
    if(letter==10 && number>0 && symbol>0){//字母、数字和符号
        return 3;
    }
    if(letter==20 && number>0 && symbol>0){//大小写字母、数字和符号
        return 5;
    }
    return 0;
 }
/**
 * 最终评分
 * @param str 
 */
export const level = (str: string) => { 
    let lengths=length(str);//长度
    let letter=letters(str);//字母
    let number=numbers(str);//数字
    let symbol=symbols(str);//符号
    let reward=rewards(str);//奖励
    let sum=lengths+letter+number+symbol+reward;
    console.log(sum);
    if(sum>=80){
        return "非常强";//非常安全
    }else if(sum>=60){
        return "强";//非常强
    }else if(sum>=40){
        return "一般";//一般
    }else if(sum>=25){
        return "弱";//弱
    }else{
        return "非常弱";//非常弱
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值