java密码复杂度匹配规则

在开发中经常需要验证字符串是否匹配纯数字,纯大写,纯小写,大写小写数字特殊字符等任意两种,特别是在密码复杂度匹配时,现添加工具类校验字符串是否满足规则

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;import java.util.*;/*** 字符串规则校验器** @version V1.0* @date 2022/7/18 18:22*/
@Slf4j
@Component
@NoArgsConstructor
@Getter
@Setter
public class StringValidator extends AbstractValidator {/*** 字符串配置信息*/private StringConfig config;/*** 单个中文汉字<br>* 参照维基百科汉字Unicode范围(https://zh.wikipedia.org/wiki/%E6%B1%89%E5%AD%97 页面右侧)*/private static final String RE_CHINESE = "\u2E80-\u2EFF\u2F00-\u2FDF\u31C0-\u31EF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uD840\uDC00-\uD869\uDEDF\uD869\uDF00-\uD86D\uDF3F\uD86D\uDF40-\uD86E\uDC1F\uD86E\uDC20-\uD873\uDEAF\uD87E\uDC00-\uD87E\uDE1F";/*** 默认构造方法** @param config 校验配置*/public StringValidator(StringConfig config) {super(config.getErrMsg());this.config = config;}/*** 支持的校验参数类型** @return 参数校验枚举*/@Overrideprotected ValidatorCheckTypeEnum supportType() {return ValidatorCheckTypeEnum.STRING;}/*** 通过配置信息初始化并返回新的校验器** @param config 配置信息* @return 新校验器*/@Overridepublic ValidatorInterface init(JSONObject config) {return new StringValidator(config.toJavaObject(StringConfig.class));}/***  校验是否通过.不通过会抛出ValidatorException* @param value 参数值*/public void validate(String value){this.validate(value, new SysModelColumnResponse());}/*** 校验是否通过,true:校验通过,false:校验不通过** @param value  当前值* @param column 上下文环境,列定义信息*/@Overridepublic void validate(String value, SysModelColumnResponse column) {// 空类型判断this.checkEmpty(value, this.config.getEmpty(), column);// 判断字符串长度this.checkLength(value, column);// 检测支持的字符类型this.checkChar(value, column);}/*** 校验字符串支持的字符** @param value  字符串* @param column 列名称*/private void checkChar(String value, SysModelColumnResponse column) {if (Objects.isNull(value)) {log.info("对象:{},属性:{},值为空字符串,不校验字符!", column.getDomainObject(), column.getName());return;}StringBuilder sb = new StringBuilder();sb.append("^");// 不包含特殊字符if (StringUtils.isNotBlank(this.config.unsupportSymbol)) {sb.append("(?![").append(ReUtil.escape(this.config.unsupportSymbol)).append("]+$)");}// 至少包含字符个数if(this.config.leastSupportType != null && this.config.leastSupportType > 1){List<String> combination = new ArrayList<>(Arrays.asList(this.config.supportType));if(StringUtils.isNotBlank(this.config.supportSymbol) && !combination.contains(SupportType.SPECIAL_CHAR.name())){combination.add(SupportType.SPECIAL_CHAR.name());}// 字符串组合Set<Set<String>> strCombination = ListUtil.combination(combination, this.config.leastSupportType-1);for(Set<String> types: strCombination){sb.append("(?![");types.forEach(c->sb.append(this.getSupportTypePattern(c)));sb.append("]+$)");}}// 包含特定字符if (ArrayUtils.isNotEmpty(this.config.supportType) || StringUtils.isNotBlank(this.config.supportSymbol)) {sb.append("[");// 包含指定类型字符if (ArrayUtils.isNotEmpty(this.config.supportType)) {for (String type : this.config.supportType) {sb.append(this.getSupportTypePattern(type));}}// 包含特殊字符if (StringUtils.isNotBlank(this.config.supportSymbol)) {sb.append(ReUtil.escape(this.config.supportSymbol));}sb.append("]");} else {sb.append(".");}// 字符串长度限制if(Objects.nonNull(this.config.minLength) || Objects.nonNull(this.config.maxLength)){sb.append("{").append(Objects.nonNull(this.config.minLength) ? this.config.minLength :"").append(",").append(Objects.nonNull(this.config.maxLength) ? this.config.maxLength: "").append("}");}else{sb.append("+");}sb.append("$");// 判断值是否匹配规则if (!ReUtil.isMatch(sb.toString(), value)) {throw this.createValidatorException(column.getName(),StrUtil.format("对象:{},属性:{},值:{}, 不匹配正则规则:{}", column.getDomainObject(), column.getName(), value, sb));}}/*** 校验字符串长度** @param value  参数值* @param column 列名称*/private void checkLength(String value, SysModelColumnResponse column) {if (Objects.isNull(value)) {log.info("对象:{},属性:{},值为空字符串,不校验字符长度!", column.getDomainObject(), column.getName());return;}// 最大长度if (Objects.nonNull(this.config.maxLength) && StringUtils.length(value) > this.config.maxLength) {throw this.createValidatorException(column.getName(),StrUtil.format("对象:{},属性:{},值:{}, 超过最大长度: {}>{}(max)", column.getDomainObject(), column.getName(), value, StrUtil.length(value), this.config.maxLength));}// 最小长度if (Objects.nonNull(this.config.minLength) && StringUtils.length(value) < this.config.minLength) {throw this.createValidatorException(column.getName(),StrUtil.format("对象:{},属性:{},值:{}, 超过最小长度: {}<{}(min)", column.getDomainObject(), column.getName(), value, StrUtil.length(value), this.config.minLength));}}/*** 判断参数是否为空类型** @param value  参数值* @param empty  空类型* @param column 属性列*/private void checkEmpty(String value, String empty, SysModelColumnResponse column) {if (StringUtils.equalsIgnoreCase(NOT_NULL.name(), empty) && Objects.isNull(value)) {throw this.createValidatorException(column.getName(),StrUtil.format("对象:{},属性:{},值:{}, 不能为NULL", column.getDomainObject(), column.getName(), value));}if (StringUtils.equalsIgnoreCase(NOT_EMPTY.name(), empty) && StringUtils.isEmpty(value)) {throw this.createValidatorException(column.getName(),StrUtil.format("对象:{},属性:{},值:{}, 不能为空字符串", column.getDomainObject(), column.getName(), value));}if (StringUtils.equalsIgnoreCase(NOT_BLANK.name(), empty) && StringUtils.isBlank(value)) {throw this.createValidatorException(column.getName(),StrUtil.format("对象:{},属性:{},值:{}, 不能为空白字符串", column.getDomainObject(), column.getName(), value));}}/*** 获取支持类型的正则表达式* @param supportType 支持类型* @return 正则表达式*/private String getSupportTypePattern(String supportType){if(SupportType.SPECIAL_CHAR.name().equalsIgnoreCase(supportType)){return ReUtil.escape(this.config.supportSymbol);}else {SupportType parse = SupportType.parse(supportType);if (parse != null) {return parse.getPattern();}}return null;}@Datapublic static class StringConfig {/*** 最大长度*/private Integer maxLength;/*** 最小长度*/private Integer minLength;/*** 支持的字符*/private String supportSymbol;/*** 不支持的字符*/private String unsupportSymbol;/*** 支持的类型*/private String[] supportType;/*** 至少包含支持类型的个数,例如:密码至少需要包含大写、小写、数字 任意2种*/private Integer leastSupportType;/*** 空类型*/private String empty;/*** 提示消息*/private String errMsg;}/*** 字符串空类型*/enum EmptyType {NOT_BLANK, NOT_EMPTY, NOT_NULL;}/*** 支持的字符类型*/@Getter@AllArgsConstructorenum SupportType {// 中文CHINESE(RE_CHINESE),// 字母GENERAL("a-zA-Z"),// 数字NUMBER("0-9"),// 大写UPPER_CASE("A-Z"),// 小写LOWER_CASE("a-z"),// 特殊字符, 会使用supportSymbol指定的字符SPECIAL_CHAR(""),;/*** 正则表达式*/private final String pattern;/*** 支持的类型* @param name 名称* @return 类型*/public static SupportType parse(String name){for (SupportType type: SupportType.values()){if(StringUtils.equalsIgnoreCase(name, type.name())){return type;}}return null;}}public static void main(String[] args) {StringConfig conf = new StringConfig();conf.setMaxLength(20);conf.setMinLength(4);conf.setSupportSymbol("!@#$%^&*()_+{}[]");conf.setUnsupportSymbol(".");conf.setSupportType(new String[]{"NUMBER","UPPER_CASE","LOWER_CASE"});conf.setLeastSupportType(2);conf.setEmpty("NOT_BLANK");conf.setErrMsg("密码校验错误");StringValidator stringValidator = new StringValidator(conf);String[] passwords = {"123456","123456.","abcdefg","abcdefg.","ABDCEDG","ABDCEDG.","!@#$%^&*()","abcdEFG","abcdEFG.","abc1233","abc1233.","ABC1234","123!@#$%^&*()","ABC!@#$%^&*()","!@#$%^&*()abc","ab123Ab","abAb!@#$","123AB!@#$","ab123!@#$","ab123Ab!@#$","ab123Ab@223^&*","委屈@123Abnd&*("};for (String password: passwords){try {stringValidator.validate(password);log.info("校验:-------------------------{} 成功", password);} catch (ValidatorException e) {log.error("参数:{},{}:{}",password,e.getMessage(), e.getErrorMessage());}}}
}

执行结果:

16:37:21.434 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:123456,null: 密码校验错误:对象:null,属性:null,值:123456, 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.439 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:123456.,null: 密码校验错误:对象:null,属性:null,值:123456., 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.439 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:abcdefg,null: 密码校验错误:对象:null,属性:null,值:abcdefg, 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.439 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:abcdefg.,null: 密码校验错误:对象:null,属性:null,值:abcdefg., 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.439 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:ABDCEDG,null: 密码校验错误:对象:null,属性:null,值:ABDCEDG, 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.439 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:ABDCEDG.,null: 密码校验错误:对象:null,属性:null,值:ABDCEDG., 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.440 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:!@#$%^&*(),null: 密码校验错误:对象:null,属性:null,值:!@#$%^&*(), 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.440 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------abcdEFG 成功
16:37:21.440 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:abcdEFG.,null: 密码校验错误:对象:null,属性:null,值:abcdEFG., 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.440 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------abc1233 成功
16:37:21.440 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:abc1233.,null: 密码校验错误:对象:null,属性:null,值:abc1233., 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$
16:37:21.441 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------ABC1234 成功
16:37:21.441 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------123!@#$%^&*() 成功
16:37:21.441 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------ABC!@#$%^&*() 成功
16:37:21.441 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------!@#$%^&*()abc 成功
16:37:21.441 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------ab123Ab 成功
16:37:21.441 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------abAb!@#$ 成功
16:37:21.442 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------123AB!@#$ 成功
16:37:21.442 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------ab123!@#$ 成功
16:37:21.442 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------ab123Ab!@#$ 成功
16:37:21.442 [main] INFO com.aimilin.common.model.validator.StringValidator - 校验:-------------------------ab123Ab@223^&* 成功
16:37:21.442 [main] ERROR com.aimilin.common.model.validator.StringValidator - 参数:委屈@123Abnd&*(,null: 密码校验错误:对象:null,属性:null,值:委屈@123Abnd&*(, 不匹配正则规则:^(?![\.]+$)(?![0-9]+$)(?![A-Z]+$)(?![!@#\$%\^&\*\(\)_\+\{\}\[\]]+$)(?![a-z]+$)[0-9A-Za-z!@#\$%\^&\*\(\)_\+\{\}\[\]]{4,20}$

因为需要设置不匹配的规则,比如至少匹配三种格式,那么久需要设置不能匹配两两组合。
列表指定元素个数求组合:

/*** 列表工具类** @author liujunguang1* @version V1.0* @date 2022/9/8 15:07*/
public class ListUtil {/*** 列表中指定元素组合* @param remainEle 元素* @param fetchCount 指定元素组合* @return 结果*/public static <T> Set<Set<T>> combination(List<T> remainEle, int fetchCount) {return combination(remainEle, new ArrayList<>(), fetchCount);}/*** 列表 组合* @param remainEle 元素列表* @param tempCollection 临时存储对象* @param fetchCount 组合元素个数* @return 组合结果*/private static <T> Set<Set<T>> combination(List<T> remainEle, List<T> tempCollection, int fetchCount) {if (CollectionUtils.isEmpty(remainEle)) {return new HashSet<>();}if (fetchCount == 1) {Set<Set<T>> eligibleCollections = new HashSet<>();// 在只差一个元素的情况下,遍历剩余元素为每个临时集合生成多个满足条件的集合for (T ele : remainEle) {Set<T> collection = new HashSet<>(tempCollection);collection.add(ele);eligibleCollections.add(collection);}return eligibleCollections;}fetchCount--;Set<Set<T>> result = new HashSet<>();// 差多个元素时,从剩余元素中取出一个,产生多个临时集合,还需要取 count-- 个元素。for (int i = 0; i < remainEle.size(); i++) {List<T> collection = new ArrayList<>(tempCollection);List<T> tempRemain = new ArrayList<>(remainEle);collection.add(tempRemain.remove(i));result.addAll(combination(tempRemain, collection, fetchCount));}return result;}
}

正则表达式:密码中至少包含大写字母、小写字母、数字、特殊字符等字符中的2种或3种

java密码复杂度匹配规则相关推荐

  1. Java 密码复杂度校验

    1,需求 复杂性:用户的密码中必须包含的字符类型,默认为中 弱:必须包含小写字母 中:必须包含小写字母.数字 强:必须包含小写字母.数字.大写字母.特殊字符(鼠标移入的提示文字相同) 注:检查密码复杂 ...

  2. java实现王者荣耀匹配规则,王者荣耀匹配机制解析_王者荣耀匹配隐藏分规则介绍...

    王者荣耀玩的人数越来越多,匹配速度也是非常之快,不过,你可有注意到匹配是有一定规则的?今天小编就来给大家介绍一下王者荣耀匹配机制解析. 王者荣耀的匹配机制至少分为三种,分别是匹配赛匹配机制,赏金赛匹配 ...

  3. java实现王者荣耀匹配规则,王者荣耀匹配机制(通俗版)

    玩了这么久的王者荣耀,也该出来分析一波了. 很多人都会有这样的疑问:为什么我们在"农药"游戏中会出现连胜之后连败的情况?而且在连胜后遇到的对手都异常强劲,而队友却无比"坑 ...

  4. Java字符串相似度匹配

    原文:http://wdhdmx.iteye.com/blog/1343856#bc2319361 package com.xfl.boot.common.utils;/*** Created by ...

  5. java实现王者荣耀匹配规则,王者荣耀:你单排总匹配到坑?是“匹配机制”因为你的这些无意触发了...

    原标题:王者荣耀:你单排总匹配到坑?是"匹配机制"因为你的这些无意触发了 单排打排位赛,队友一个比一个坑,我有一个程序猿朋友,他告诉我底层的匹配机制还是沿用的Dota,王者荣耀,只 ...

  6. java实现王者荣耀匹配规则,王者荣耀匹配机制故意安排队友,看看队友构成就知道了...

    王者荣耀的匹配机制一直受到玩家诟病. 很多人发现只要一连胜或者晋升.降级,马上给你安排队友. 晋级时你的队友就不给力,费劲也难上去.降级的时候队友就很强,对面都跟弱鸡一样.连胜必须给你连败,始终给你维 ...

  7. java实现行政区域划分,行政区划正则表达式匹配规则及java实现

    行政区划正则表达式匹配规则及java实现 行政区划正则表达式匹配规则及java实现 (.*?省|.*?市|.*?自治区)?(.*?市|.*?县|.*?区|.*?自治州)?(.*?县|.*?区)(.*? ...

  8. Java实现标题相似度计算,文本内容相似度匹配,Java通过SimHash计算标题文本内容相似度

     目录 一.前言 二.关于SimHash 补充知识 一).什么是海明距离 二).海明距离的应用 三).什么是编辑距离 三.SimHash算法的几何意义和原理 一).SimHash算法的几何意义 二). ...

  9. Java中intentfiler_【Android - 组件】之IntentFilter的匹配规则

    我们知道,Activity的启动模式分为两种,分别是显式启动和隐式启动.显式启动需要明确的指定被启动的对象的组件信息,包括包名和类名:而隐式启动需要 Intent 能够匹配目标组件的 IntentFi ...

最新文章

  1. 假如AI也会diss人类,他们会这样.....
  2. 一文详解目标跟踪中的相关滤波
  3. 码教授告诉你人工智能如今涉及的领域你无法想象
  4. Android CardView 开发过程中要注意的细节
  5. PHP函数库之BC高精确度函数库
  6. 【数据库】Ubuntu18.04安装MySQL详解
  7. C#判断一个类中有无指定名称的方法
  8. 前端学习(2455):layout处理
  9. 依据imu姿态角计算z轴倾角_[姿态估计] DenseFusion详解
  10. SLAM_相机与imu的融合基础知识
  11. 9款超级好看有创意的表白网页源码
  12. BP神经网络算法推导过程
  13. ZigBee-CC2530单片机 - 实现软件自动复位
  14. rational rose mysql_用Rational Rose逆向工程(java)生成类图(教程和错误解决)
  15. 【IP SSL】内网IP SSL证书Nginx部署
  16. 攻防世界逆向入门题之logmein
  17. “风味人间”与计算机程序设计艺术《禅与计算机程序设计艺术》
  18. ios下overflow:scoll中卡顿问题
  19. 【数据处理与分析】matplotlib快速入门
  20. 基于JAVA家电售后管理系统计算机毕业设计源码+数据库+lw文档+系统+部署

热门文章

  1. Unity3D规则之Unity Root Motion / Bake into Pose 的问题
  2. CryEngine3-CE3本地化系统入门、UI字体更换
  3. 百度快照更新与倒退的官方解释
  4. 提升百度快照更新频率的方法
  5. 大地诗景:银川 (转载)
  6. 营销CRM软件(销售管理工具)让客户都成为回头客
  7. VC++对Access数据库的操作(查询、插入、更新、删除等)
  8. 又躺赚1亿?东方联盟创始人郭盛华,会的仅仅是技术吗?
  9. 802.11ac路由选购技术攻略
  10. Java生成动态生成水印图片,为图片打水印. Java为图片打水印