工具介绍

公司在做认证系统时,由于安全需要,屏蔽掉弱密码,需要检测用户输入的密码强度。计算方法参考http://www.passwordmeter.com/  的计算方法,但passwordmeter本身计算存在些许错误,且无java版本,后端无法对密码进行二次校验(后端不信任前端任何验证)。于是开发了这个密码强度检验函数。

校验函数通过100W随机密码测试,100W条数据中无一条错误,如果你在测试过程中发现错误,请评论区留下测试结果不一致的密码字符串,这边将会修复。

  • 感谢 上海智隆信息 张晋荣 提供的帮助

java 密码复杂度 校验 正则 java密码强度检验工具_java 密码复杂度 校验 正则

验证算法

说明: 表格中  n代表存在该项目出现的次数, len代表密码总长度

密码最低要求:

  • 最少8个字符
  • 包含以下3-4项
  1. 大写字母
  2. 小写字母
  3. 数字
  4. 符号

加分项目

算法

密码长度

+(n*4)

大写字母个数

+((len-n)*2)

小写字母个数

+((len-n)*2)

数字个数

+(n*4)

符号个数

+(n*6)

中间数字或符号个数

+(n*2)

是否满足要求

+(n*2)

减分项目

算法

只有字母

-n

只有数字

-n

重复的字符(忽略大小写) 

算法未知,详情见代码

连续出现大写字母

-(n*2)

连续出现小写字母

-(n*2)

连续出现数字

-(n*2)

大于3个的按顺序出现的大写字母, 如:ABCD(n从第3个字母开始计数)

-(n*3)

大于3个的按顺序出现的小写字母(n从第3个字母开始计数) 

-(n*3)

大于3个的按顺序出现的数字(n从第3个字母开始计数)  

-(n*3)

 

  • JavaScript代码
/*
 * @Descripttion:
 * @version: 0.0.1
 * @Author: ZHJI
 * @Date: 2019-09-25 11:34:00
 * @LastEditors: ZHJI
 * @LastEditTime: 2019-09-25 13:23:14
 */


console.log(chkPass("h5(6^u6Ch%4A2v0"))

function chkPass(password) {
  if (!password) {
	  return -1
  }
  if (password.indexOf(' ') !== -1) {
	   return -1
  }
  this.passwordLength = password.length
  this.lowerLetterCount = 0
  this.upperLetterCount = 0
  this.numberLetterCount = 0
  this.charLetterCount = 0
  let a =getPwdLowerLetterScore(password)
  let b =getPwdUpperLetterScore(password)
  let c =getPwdLengthScore(password)
  let d =getPwdNumberLetterScore(password)
  let e =getPwdCharLetterScore()
  let f =getPwdNumberOrCharInPasswordScore(password)
  let g =getPwdLowRequireScore(password)
  let h =getPwdOnlyEnglishLetterScore(password)
  let i =getPwdOnlyNumberLetterScore(password)
  let j =getPwdRepeatedLetterScore(password)
  let k =getPwdContinuouUpperLetterScore(password)
  let l =getPwdContinuouLowerLetterScore(password)
  let m =getPwdContinuouLowerNumberScore(password)
  let n =getPwdContinuouLetterScore(password)
  let o =getPwdContinuouNumberScore(password)
  let p =getPwdContinuouChartScore(password)
  console.log('小写字母得分:' + a)
  console.log('大写字母得分:' + b)
  console.log('密码长度的得分:' + c)
  console.log('数字得分:' + d)
  console.log('符号得分:' + e)
  console.log(' 中间穿插数字或符号:' + f)
  console.log('最低要求得分:' + g)
  console.log('仅仅包含字母:' + h)
  console.log('仅仅包含数字:' + i)
  console.log('重复字符:' + j)
  console.log('连续大写字母:' + k)
  console.log('连续小写字母:' + l)
  console.log('连续数:' + m)
  console.log('连续字母 (3):' + n)
  console.log('连续数字(3):' + o)
  console.log('连续符号(3):' + p)
  return a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p
  /**
   * 获取密码长度得分
   * @param {String} password
   */
  function getPwdLengthScore(password) {
    return 4 * this.passwordLength
  }
  /**
   * 获取小写字母得分
   * @param {String} password
   */
  function getPwdLowerLetterScore(password) {
    var lowerLetterCount = 0
    for (let i = 0; i < this.passwordLength; i++) {
      if (password.charCodeAt(i) >= 'a'.charCodeAt(0) && password.charCodeAt(i) <= 'z'.charCodeAt(0)) {
        lowerLetterCount++
      }
    }
    this.lowerLetterCount = lowerLetterCount
    if (lowerLetterCount > 0) {
      return (this.passwordLength - lowerLetterCount) * 2
    } else {
      return 0
    }
  }
  /**
   * 获取大写字母得分
   * @param {String} password
   */
  function getPwdUpperLetterScore(password) {
    var upperLetterCount = 0

    for (let i = 0; i < this.passwordLength; i++) {
      if (password.charCodeAt(i) >= 'A'.charCodeAt(0) && password.charCodeAt(i) <= 'Z'.charCodeAt(0)) {
        upperLetterCount++
      }
    }
    this.upperLetterCount = upperLetterCount
    if (upperLetterCount > 0) {
      return (this.passwordLength - upperLetterCount) * 2
    } else {
      return 0
    }
  }
  /**
    * 获取数字得分
    * @param {String } password
    */
  function getPwdNumberLetterScore(password) {
    let numberLetterCount = 0
    for (let i = 0; i < this.passwordLength; i++) {
      if (password.charCodeAt(i) >= '0'.charCodeAt(0) && password.charCodeAt(i) <= '9'.charCodeAt(0) ){
        numberLetterCount++
      }
    }
    this.numberLetterCount = numberLetterCount
    return this.passwordLength === numberLetterCount ? 0 : numberLetterCount * 4
  }

  /**
   * 获取符号得分
   */
  function getPwdCharLetterScore() {
    this.charLetterCount = this.passwordLength - this.lowerLetterCount - this.upperLetterCount - this.numberLetterCount
    return this.charLetterCount * 6
  }
  /**
   * 密码中间穿插数字或符号
   * @param {String} password
   */
  function getPwdNumberOrCharInPasswordScore(password) {
    var result = this.numberLetterCount + this.charLetterCount
    if (!(
	(password.charCodeAt(0) >= 'A'.charCodeAt(0) && password.charCodeAt(0) <= 'Z'.charCodeAt(0) )
	|| 
	(password.charCodeAt(0) >= 'a'.charCodeAt(0) && password.charCodeAt(0) <= 'z'.charCodeAt(0))
	) ){
      result--
    }
    if (!(
	(password.charCodeAt(this.passwordLength - 1) >= 'A'.charCodeAt(0) && password.charCodeAt(this.passwordLength - 1) <= 'Z'.charCodeAt(0)) 
	|| 
	(password.charCodeAt(this.passwordLength - 1) >= 'a'.charCodeAt(0) && password.charCodeAt(this.passwordLength - 1) <= 'z'.charCodeAt(0))
	) ){
      result--
    }
    return result * 2
  }
  /**
   * 获取最低要求得分
   * @param {*} password
   */
  function getPwdLowRequireScore(password) {
    var result = 0
    if (this.passwordLength >= 8) {
      result++
    }
    if (this.upperLetterCount > 0) {
      result++
    }
    if (this.lowerLetterCount > 0) {
      result++
    }
    if (this.numberLetterCount > 0) {
      result++
    }
    if (this.charLetterCount > 0) {
      result++
    }
    //  长度没有8位或者3项条件没有满足3个以上 直接返回0
    if (this.passwordLength < 8 || result < 4) {
      return 0
    } else {
      return result * 2
    }
  }
  /**
   *  仅仅包含字母
   * @param {String} password
   */
  function getPwdOnlyEnglishLetterScore(password) {
    return this.passwordLength === this.lowerLetterCount + this.upperLetterCount ? -this.passwordLength : 0
  }
  /**
 *  仅仅包含数字
 * @param {String } password
 */
  function getPwdOnlyNumberLetterScore(password) {
    return this.passwordLength === this.numberLetterCount ? -this.passwordLength : 0
  }
  /**
 * 重复字符
 * @param {String} password
 */
  function getPwdRepeatedLetterScore(password) {
    var nRepChar = 0
    var nUnqChar = 0
    var nRepInc = 0
    var arrPwd = password.replace('\s+', '').split('')
    var arrPwdLen = arrPwd.length

    for (let a = 0; a < arrPwdLen; a++) {
      var bCharExists = false
      for (let b = 0; b < arrPwdLen; b++) {
        if (arrPwd[a]===arrPwd[b] && a !== b) { /* repeat character exists */
          bCharExists = true
          nRepInc += Math.abs(arrPwdLen / (b - a))
        }
      }
      if (bCharExists) {
        nRepChar++
        nUnqChar = arrPwdLen - nRepChar

        nRepInc = ((nUnqChar !== 0) ? Math.ceil(nRepInc / nUnqChar) : Math.ceil(nRepInc))
      }
    }
    return -nRepInc
  }
  /**
 *  连续大写字母
 * @param {String } password
 */
  function getPwdContinuouUpperLetterScore(password) {
    var j = 0
    for (let i = 0; i < password.length - 1; i++) {
      if (password.charCodeAt(i) >= 'A'.charCodeAt(0) && password.charCodeAt(i) <= 'Z'.charCodeAt(0) ){
        if (password.charCodeAt(i + 1) >= 'A'.charCodeAt(0) && password.charCodeAt(i + 1) <= 'Z'.charCodeAt(0)) {
          j++
        }
      }
    }
    return -2 * j
  }
  /**
   * 连续小写字母
   * @param {String} password
   */
  function getPwdContinuouLowerLetterScore(password) {
    var j = 0
    for (let i = 0; i < password.length - 1; i++) {
      if (password.charCodeAt(i) >= 'a'.charCodeAt(0) && password.charCodeAt(i) <= 'z'.charCodeAt(0)) {
        if (password.charCodeAt(i + 1) >= 'a'.charCodeAt(0) && password.charCodeAt(i + 1) <= 'z'.charCodeAt(0)) {
          j++
        }
      }
    }
    return -2 * j
  }
  /**
  * 连续数
  * @param {String} password
  */
  function getPwdContinuouLowerNumberScore(password) {
    var j = 0
    for (let i = 0; i < password.length - 1; i++) {
      if (password.charCodeAt(i) >= '0'.charCodeAt(0) && password.charCodeAt(i) <= '9'.charCodeAt(0) ){
        if (password.charCodeAt(i + 1) >= '0'.charCodeAt(0) && password.charCodeAt(i + 1) <= '9'.charCodeAt(0) ) {
          j++
        }
      }
    }
    return -2 * j
  }
  /**
  *  连续字母 3+ (like abc)
  * @param {String} password
  */
  function getPwdContinuouLetterScore(password) {
    password = password.toUpperCase()
    var j = 0
    for (var i = 0; i < password.length - 2; i++) {
      if (password.charCodeAt(i) >= 'A'.charCodeAt(0) && password.charCodeAt(i) <= 'Z'.charCodeAt(0)) {
        if ((password.charCodeAt(i + 1) === password.charCodeAt(i) + 1) && (password.charCodeAt(i + 2) === password.charCodeAt(i) + 2)) {
          j++
        }
        if ((password.charCodeAt(i + 1) === password.charCodeAt(i) - 1) && (password.charCodeAt(i + 2) === password.charCodeAt(i) - 2)) {
          j++
        }
      }
    }
    return -3 * j
  }
  /**
   * 连续数字 3+ (like 123)
   * @param {String } password
   */
  function getPwdContinuouNumberScore(password) {
    var j = 0
    for (var i = 0; i < password.length - 2; i++) {
		
      if (password.charCodeAt(i) >= '0'.charCodeAt(0) && password.charCodeAt(i) <= '9'.charCodeAt(0) ) {
        if ((password.charCodeAt(i + 1) === password.charCodeAt(i) + 1) && (password.charCodeAt(i + 2) === password.charCodeAt(i) + 2)) {
          j++
        }
        if ((password.charCodeAt(i + 1) === password.charCodeAt(i) - 1) && (password.charCodeAt(i + 2) === password.charCodeAt(i) - 2)) {
          j++
        }
      }
    }
    return -3 * j
  }
  /**
   * 连续符号 3+ (like !@#)
   * @param {String} password
   */
  function getPwdContinuouChartScore(password) {
    var nSeqSymbol = 0
    var dict = ')!@#$%^&*()'
    for (let s = 0; s < 8; s++) {
      var sFwd = dict.substring(s, s + 3)
      if (password.indexOf(sFwd) !== -1 || password.split("").reverse().join("").indexOf(sFwd) != -1) {
        nSeqSymbol++
      }
    }
    return -3 * nSeqSymbol
  }
}
  • java代码片段
package Tool;

import java.util.Locale;
import java.util.regex.Pattern;

/**
 * 
 * @author ZHJI
 *
 */

public class Main {
	
	private int passwordLength = 0;
	private int lowerLetterCount =0;
	private int upperLetterCount =0;
	private int numberLetterCount =0;
	private int charLetterCount =0;
	
	public static void main(String[] args) throws Exception  {
		Main testMain = new Main();
		System.out.println(testMain.chkPass("test123456"));
	}
	
	
	public int chkPass(String password){
		if (password != null && !password.isEmpty()) {
			
			this.passwordLength = password.length();
			int a = this.getPwdLowerLetterScore(password);
			int b = this.getPwdUpperLetterScore(password);
			int c = this.getPwdLengthScore(password);
			int d = this.getPwdNumberLetterScore(password);
			int e = this.getPwdCharLetterScore();
			int f = this.getPwdNumberOrCharInPasswordScore(password);
			int g = this.getPwdLowRequireScore(password);
			int h = this.getPwdOnlyEnglishLetterScore(password);
			int i = this.getPwdOnlyNumberLetterScore(password);
			int j = this.getPwdRepeatedLetterScore(password);
			int k = this.getPwdContinuouUpperLetterScore(password);
			int l = this.getPwdContinuouLowerLetterScore(password);
			int m = this.getPwdContinuouLowerNumberScore(password);
			int n = this.getPwdContinuouLetterScore(password);
			int o = this.getPwdContinuouNumberScore(password);
			int p = this.getPwdContinuouChartScore(password);
			System.out.println("小写字母得分:" +a);
			System.out.println("大写字母得分:" + b);
			System.out.println("密码长度的得分:" +c);
			System.out.println("数字得分:" + d);
			System.out.println("符号得分:" + e);
			System.out.println(" 中间穿插数字或符号:" +f );
			System.out.println("最低要求得分:" +g);
			System.out.println("仅仅包含字母:" +h );
			System.out.println("仅仅包含数字:" +i );
			System.out.println("重复字符:" +j );
			System.out.println("连续大写字母:" +k );
			System.out.println("连续小写字母:" +l );
			System.out.println("连续数:" + m);
			System.out.println("连续字母 (3):" + n);
			System.out.println("连续数字(3):" +o );
			System.out.println("连续符号(3):" +p );
			return a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p;
		}else {
			System.out.println("传入密码不合法" + password);
			return 0;
		}
	}
	
	
	/*
	 *  <i>获取密码长度的得分</i>
	 */
	private int getPwdLengthScore(String password) {
		
		return 4*this.passwordLength;
		
	}
	
	/*
	 *  <i>获取小写字母得分</i>
	 */
	private int getPwdLowerLetterScore(String password) {
		int lowerLetterCount = 0;
		
		 for(int i=0;i<this.passwordLength;i++){
			
			 if (password.charAt(i)>='a' && password.charAt(i)<='z' ) {
				 lowerLetterCount++;
			}
		 }
		 this.lowerLetterCount = lowerLetterCount;
		 if (lowerLetterCount>0) {
			 return (this.passwordLength - lowerLetterCount)*2;
		}else {
			return 0;
		}
		 
	}
	
	/*
	 *  <i>获取大写字母得分</i>
	 */
	private int getPwdUpperLetterScore(String password) {
		int upperLetterCount = 0;
		
		 for(int i=0;i<this.passwordLength;i++){
			 if (password.charAt(i)>='A' && password.charAt(i)<='Z' ) {
				 upperLetterCount++;
			}
		 }
		 this.upperLetterCount = upperLetterCount;
		 if (upperLetterCount>0) {
			 return (this.passwordLength - upperLetterCount)*2;
		}else {
			return 0;
		}
		
	}
	
	/*
	 *  <i>获取数字得分</i>
	 */
	private int getPwdNumberLetterScore(String password) {
		int numberLetterCount = 0;
		 for(int i=0;i<this.passwordLength;i++){
			 if (password.charAt(i)>='0' && password.charAt(i)<='9' ) {
				 numberLetterCount++;
			}
		 }
		 this.numberLetterCount = numberLetterCount;
		 return this.passwordLength == numberLetterCount?0:numberLetterCount*4;
	}
	/*
	 *  <i>获取符号得分</i>
	 */
	private int getPwdCharLetterScore() {
		 this.charLetterCount = this.passwordLength - this.lowerLetterCount - this.upperLetterCount - this.numberLetterCount;
		 return this.charLetterCount*6;
	}
	
	/*
	 *  <i>密码中间穿插数字或符号</i>
	 */
	private int getPwdNumberOrCharInPasswordScore(String password) {
		int result = this.numberLetterCount+this.charLetterCount;
		if (!((password.charAt(0)>='A' && password.charAt(0)<='Z')|| (password.charAt(0)>='a' && password.charAt(0)<='z'))) {
			result--;
		}
		if (!((password.charAt(this.passwordLength-1)>='A' && password.charAt(this.passwordLength-1)<='Z')|| (password.charAt(this.passwordLength-1)>='a' && password.charAt(this.passwordLength-1)<='z'))) {
			result--;
		}
		 return result*2;
	}
	
	/*
	 *  <i>最低要求得分</i>
	 */
	private int getPwdLowRequireScore(String password) {
		int result = 0;
		if (this.passwordLength>=8) {
			result++;
		}
		if (this.upperLetterCount>0) {
			result++;
		}
		if (this.lowerLetterCount>0) {
			result++;
		}
		if (this.numberLetterCount>0) {
			result++;
		}
		if (this.charLetterCount>0) {
			result++;
		}
		//  长度没有8位或者3项条件没有满足3个以上 直接返回0
		if (this.passwordLength<8 || result<4) {
			return 0;
		}else {
			return result*2;
		}
	}
	
	/*
	 *  <i>仅仅包含字母</i>
	 */
	private int getPwdOnlyEnglishLetterScore(String password) {
		
		return this.passwordLength == this.lowerLetterCount + this.upperLetterCount?-this.passwordLength:0;
	}
	
	/*
	 *  <i>仅仅包含数字</i>
	 */
	private int getPwdOnlyNumberLetterScore(String password) {
		
		return this.passwordLength == this.numberLetterCount ?-this.passwordLength:0;
	}
	
	/*
	 *  <i>重复字符 </i>
	 */
	private int getPwdRepeatedLetterScore(String password) {
		int nRepChar=0,nUnqChar=0;
		double nRepInc=0;
		String[] arrPwd = password.replace("\\s+","").split("\\s*");
		int arrPwdLen = arrPwd.length;
		
		for (int  a=0; a < arrPwdLen; a++) {
			boolean bCharExists = false;
			for (int  b=0; b < arrPwdLen; b++) {
				if (arrPwd[a].equals(arrPwd[b]) && a != b) { /* repeat character exists */
					bCharExists = true;
					nRepInc += Math.abs(arrPwdLen/(double)(b-a));
				}
			}
			if (bCharExists) { 
				nRepChar++; 
				nUnqChar = arrPwdLen-nRepChar;
				
				nRepInc =  ((nUnqChar!=0) ? Math.ceil(nRepInc/nUnqChar) : Math.ceil(nRepInc)); 
			}
		}
		return -(int)nRepInc;
	}

	
	/*
	 *  <i>连续大写字母 </i>
	 */
	private int getPwdContinuouUpperLetterScore(String password) {
		 int j=0;
	        char[] c = password.toCharArray();
	        for (int i = 0; i < c.length-1; i++) {
	            if(Pattern.compile("[A-Z]").matcher(c[i]+"").find()){
	                if (Pattern.compile("[A-Z]").matcher(c[i+1]+"").find()) {
	                    j++;
	                }
	            }
	        }
	        return -2*j;
	}
	
	/*
	 *  <i>连续小写字母 </i>
	 */
	private int getPwdContinuouLowerLetterScore(String password) {
		 int j=0;
	        char[] c = password.toCharArray();
	        for (int i = 0; i < c.length-1; i++) {
	            if(Pattern.compile("[a-z]").matcher(c[i]+"").find()){
	                if (Pattern.compile("[a-z]").matcher(c[i+1]+"").find()) {
	                    j++;
	                }
	            }
	        }
	        return -2*j;
	}
	
	/*
	 *  <i>连续数 </i>
	 */
	private int getPwdContinuouLowerNumberScore(String password) {
		int j=0;
        char[] c = password.toCharArray();
        for (int i = 0; i < c.length-1; i++) {
            if(Pattern.compile("[0-9]").matcher(c[i]+"").find()){
                if (Pattern.compile("[0-9]").matcher(c[i+1]+"").find()) {
                    j++;
                }
            }
        }
        return -2*j;
	}
	
	 public int getPwdContinuouLetterScore(String password){
	        int j=0;
	        char[] c = password.toLowerCase(Locale.CHINA).toCharArray();
	        for (int i = 0; i < c.length-2; i++) {
	            if (Pattern.compile("[a-z]").matcher(c[i]+"").find()) {
	                if ((c[i+1]==c[i]+1) && (c[i+2]==c[i]+2)) {
	                    j++;
	                }
	                if ((c[i+1]==c[i]-1) && (c[i+2]==c[i]-2)) {
	                    j++;
	                }
	            }
	        }
	        return -3*j;
	    }
	 public int getPwdContinuouNumberScore(String password){
	        int j=0;
	        char[] c = password.toLowerCase(Locale.CHINA).toCharArray();
	        for (int i = 0; i < c.length-2; i++) {
	            if (Pattern.compile("[0-9]").matcher(c[i]+"").find()) {
	                if ((c[i+1]==c[i]+1) && (c[i+2]==c[i]+2)) {
	                    j++;
	                }
	                if ((c[i+1]==c[i]-1) && (c[i+2]==c[i]-2)) {
	                    j++;
	                }
	            }
	        }
	        return -3*j;
	    }
	 public int getPwdContinuouChartScore(String password){
		 int nSeqSymbol = 0;
		 String dict = ")!@#$%^&*()";
		 for (int s=0; s < 8; s++) {
				String sFwd = dict.substring(s,s+3);
				if (password.indexOf(sFwd) != -1 || new StringBuilder(password).reverse().toString().indexOf(sFwd) != -1) {
					nSeqSymbol++; 
				}
		}
		 return -3*nSeqSymbol;
	    
	 }
}
  • 最后更新时间:2019/09/25 16:23