Проверка отсутствия последовательных символов в пароле с клавиатуры

Мне необходимо проверить, есть ли в пароле(не менее 8 символов), вводимом пользователем последовательно набранные с клавиатуры символы в прямом или обратном порядке не больше 4: "yuio", "oiuy", проверка в нижнем регистре.


Ответы (2 шт):

Автор решения: Nowhere Man

Вариант решения -- построить массив/список строк минимальной запрещённой длины (в данном случае 5 символов), и на его основе построить регулярное выражение при помощи логического ИЛИ |.

// строчные буквы по рядам стандартной раскладки в прямом и обратном порядке
private static final String[] KEYS = {
    "qwertyuiop", "poiuytrewq",  // верхний ряд
    "asdfghjkl",  "lkjhgfdsa",   // средний ряд
    "zxcvbnm",    "mnbvcxz"      // нижний ряд
};

private static final int MIN_BAD_LENGTH = 5;

private static final String FORBIDDEN_PARTS = Arrays.stream(KEYS)
    .flatMap(s -> IntStream.rangeClosed(0, s.length() - MIN_BAD_LENGTH)
        .mapToObj(i -> s.substring(i, i + MIN_BAD_LENGTH))
    )
    .collect(Collectors.joining("|", "(", ")"));
// (qwert|werty|ertyu|rtyui|tyuio|yuiop|poiuy|oiuyt|iuytr|...|nbvcx|bvcxz

private static final Pattern TOO_LONG = Pattern.compile(FORBIDDEN_PARTS);

Соответственно для проверки строки (пароля) на наличие "длинных" последовательностей достаточно будет использовать метод Matcher::find

public static boolean hasLongKeyPattern(String str) {
    return null != str && TOO_LONG.matcher(str).find();
}

Если используется популярный способ валидации пароля при помощи регулярного выражения, проверяющей наличие букв разного регистра, цифры, и минимальной длины типа такого:
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$,
то можно было бы "встроить" требуемую проверку в такую регулярку при помощи негативного просмотра вперёд (negative lookahead) ?!, и проверять пароль при помощи метода matches:

private static Pattern VALID_PASSWORD = Pattern.compile("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?!.*" + FORBIDDEN_PARTS + ").{8,}$");

// ...
VALID_PASSWORD.matcher("1aQweryUiop").matches() // true
VALID_PASSWORD.matcher("2qwertAsd").matches() // false

Онлайн демо

→ Ссылка
Автор решения: svil

Достаточно добавить в одну строку и проверять в одну сторону и другую

Set<String> sequences = Set.of(
                   "qwertyuiop[]\asdfghjklzxcvbnm,./1234567890-=~@#$%^&*()_+");
→ Ссылка