ᕕ( ᐛ )ᕗ yrx's Blog

Java密码校验

package org.example;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

// 密码 8-16位
// 只能包含字母 数字 及符号~!@#$%^&_
// 不包含用户名
// 不包含3个及以上重复、连续及键盘排序字符
public class PwdValidator {
    // 允许的特殊字符
    private static final String SPECIAL_CHARS = "~!@#$%^&_";



    public static boolean validatePassword(String password, String username) {
        // 校验长度8-16位
        if (password.length() < 8 || password.length() > 16) {
            System.out.println("密码长度为 8 到 16位");
            return false;
        }

        // 只能包含字母 数字 及符号~!@#$%^&_
        if (!Pattern.matches("^[a-zA-Z0-9" + Pattern.quote(SPECIAL_CHARS) + "]+$", password)) {
            return false;
        }
        // 密码不包含用户名
//        if(password.toLowerCase().contains(username.toLowerCase())) {
//            System.out.println("密码不能包含用户名");
//            return false;
//        }
        Pattern pattern = Pattern.compile(Pattern.quote(username), Pattern.CASE_INSENSITIVE);
        if (pattern.matcher(password).find()) {
            System.out.println("密码不能包含用户名");
            return false;
        }

        // 不包含3个及以上重复字符
//        if(hasRepeatedChars(password)){
//            System.out.println("不能包含3个及以上重复字符");
//            return false;
//        }
        if (Pattern.compile("(.)\\1{2,}").matcher(password).find()) {
            System.out.println("不能包含3个及以上重复字符");
            return false;
        }
        // 不包含3个及以上连续字符
        if(hasSequentialChars(password)){
            System.out.println("不能包含3个及以上连续字符");
            return false;
        }
        // 不包含3个及以上键盘排序字符
        if(hasKeyboardSequence2(password)){
            System.out.println("不能包含3个及以上键盘排序字符");
            return false;
        }
        return true;
    }

    private static boolean hasSequentialChars(String password) {
        password = password.toLowerCase();
        for (int i = 0; i < password.length() - 2; i++) {
            char c1 = password.charAt(i);
            char c2 = password.charAt(i + 1);
            char c3 = password.charAt(i + 2);
            // 检查升序连续
            if (c1 + 1 == c2 && c2 + 1 == c3) {
                return true;
            }
            // 检查降序连续
            if (c1 - 1 == c2 && c2 - 1 == c3) {
                return true;
            }
        }
        return false;
    }

//    private static boolean hasRepeatedChars(String password) {
//        for (int i = 0; i < password.length() - 2; i++) {
//            char c = password.charAt(i);
//            if (c == password.charAt(i + 1) && c == password.charAt(i + 2)) {
//                return true;
//            }
//        }
//        return false;
//    }
//
//    private static boolean hasKeyboardSequence1(String password) {
//        password = password.toLowerCase();
//        for (String str : KEYBOARD_SEQUENCES) {
//            for (int i = 0; i < str.length() - 2; i++) {
//                // 顺序
//                String sequence = str.substring(i, i + 3);
//                // 逆序
//                String reverseSequence = new StringBuilder(sequence).reverse().toString();
//
//                if (password.contains(sequence) || password.contains(reverseSequence)) {
//                    return true;
//                }
//            }
//        }
//        return false;
//    }

    private static boolean hasKeyboardSequence2(String password) {
        // 定义键盘布局(Shift状态)
        List<List<Character>> keyboard1 = Arrays.asList(
                Arrays.asList('!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+'),
                Arrays.asList('q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '{', '}', '|'),
                Arrays.asList('a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ':', '"'),
                Arrays.asList('z', 'x', 'c', 'v', 'b', 'n', 'm', '<', '>', '?')
        );
        // 定义键盘布局(非Shift状态)
        List<List<Character>> keyboard2 = Arrays.asList(
                Arrays.asList('1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='),
                Arrays.asList('q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\'),
                Arrays.asList('a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\''),
                Arrays.asList('z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/')
        );

        char[] chars = password.toLowerCase().toCharArray();
        int[] y = new int[chars.length]; // 行坐标
        int[] x = new int[chars.length]; // 列坐标

        // 求每个字符的位置 x,y
        for(int c = 0; c < chars.length; c++) {
            y[c] = 0; // 当做~`键处理
            x[c] = -1;
            // 先在c1中查找
            for (int i = 0; i < keyboard1.size(); i++) {
                for (int j = 0; j < keyboard1.get(i).size(); j++) {
                    if (chars[c] == keyboard1.get(i).get(j)) {
                        y[c] = i;
                        x[c] = j;
                    }
                }
            }
            if (x[c] != -1) continue;
            // 如果在c1中没找到,在c2中查找
            for (int i = 0; i < keyboard2.size(); i++) {
                for (int j = 0; j < keyboard2.get(i).size(); j++) {
                    if (chars[c] == keyboard2.get(i).get(j)) {
                        y[c] = i;
                        x[c] = j;
                    }
                }
            }
        }
//        System.out.println("x:"+Arrays.toString(x));
//        System.out.println("y:"+Arrays.toString(y));
        // 判断是否键盘连续
        for (int c = 1; c < chars.length-1; c++) {
            // 检查水平方向(同一行连续)
            if (y[c - 1] == y[c] && y[c] == y[c + 1]) {
                if ((x[c - 1] + 1 == x[c] && x[c] + 1 == x[c + 1]) ||
                        (x[c + 1] + 1 == x[c] && x[c] + 1 == x[c - 1])) {
                    return true;
                }
            }
            // 检查垂直方向(同一列连续)
            else if (x[c - 1] == x[c] && x[c] == x[c + 1]) {
                if ((y[c - 1] + 1 == y[c] && y[c] + 1 == y[c + 1]) ||
                        (y[c + 1] + 1 == y[c] && y[c] + 1 == y[c - 1])) {
                    return true;
                }
            }
            // 检查斜向 如 8uhb bhu8(右上到左下 或者 左下到右上)
            else if (
                    x[c-1] - 1 == x[c] && x[c] - 1 == x[c+1] && y[c-1] + 1 == y[c] && y[c] + 1 == y[c+1] ||
                            x[c-1] + 1 == x[c] && x[c] + 1 == x[c+1] && y[c-1] - 1 == y[c] && y[c] - 1 == y[c+1]
            ) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        PwdValidator.validatePassword("16charslongpass~", "user");
    }
}

#Java