Проверка отсутствия последовательных символов в пароле с клавиатуры
Мне необходимо проверить, есть ли в пароле(не менее 8 символов), вводимом пользователем последовательно набранные с клавиатуры символы в прямом или обратном порядке не больше 4: "yuio", "oiuy", проверка в нижнем регистре.
Ответы (2 шт):
Вариант решения -- построить массив/список строк минимальной запрещённой длины (в данном случае 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
Достаточно добавить в одну строку и проверять в одну сторону и другую
Set<String> sequences = Set.of(
"qwertyuiop[]\asdfghjklzxcvbnm,./1234567890-=~@#$%^&*()_+");