许多在线网络平台要求用户在注册时输入强密码。此策略有助于减少用户数据对任何黑客攻击的脆弱性。
在本文中,我们将创建一个带有注册页面的简单表单。在继续本教程之前,您应该对使用 Spring 框架的 Java 有基本的了解。
什么是帕赛?
Passay是一个基于Java的密码生成和验证库。它建立在成功的基础上,并提供了一个全面且可扩展的功能集。vt-password
技术栈
- 节点.js。
- 角度 9.
- 弹簧启动 2.
- Maven 3.6.1.
- 爪哇 8.
- 吉特。
Maven Dependency
使用 Spring Initializr 生成具有以下依赖项的 Spring boot 2 项目:web、lombok、spring-boot-starter-validation。
然后添加 Passay 依赖项以管理验证策略。
-
<dependency>
-
<groupId>org.passay
</groupId>
-
<artifactId>passay
</artifactId>
-
<version>1.6.0
</version>
-
</dependency>
您可以在此处找到所有版本。
使用包含要验证的信息的类。UserData
-
package com.passay.sample.custompasswordvalidation.model;
-
-
import com.passay.sample.custompasswordvalidation.annotation.PasswordValueMatch;
-
import com.passay.sample.custompasswordvalidation.annotation.ValidPassword;
-
import lombok.*;
-
-
import javax.validation.constraints.Email;
-
import javax.validation.constraints.NotBlank;
-
import javax.validation.constraints.NotEmpty;
-
import javax.validation.constraints.NotNull;
-
-
/**
-
* <h2>UserData</h2>
-
*
-
* @author aek
-
*/
-
@PasswordValueMatch.List({
-
@PasswordValueMatch(
-
field = "password",
-
fieldMatch = "confirmPassword",
-
message = "Passwords do not match!"
-
)
-
})
-
@AllArgsConstructor
-
@NoArgsConstructor
-
@Getter
-
@Setter
-
@ToString
-
public
class
UserData {
-
-
-
@NonNull
-
@NotBlank(message = "username is mandatory")
-
private String username;
-
-
@NotNull
-
@NotEmpty
-
@Email
-
private String email;
-
-
-
@ValidPassword
-
@NonNull
-
@NotBlank(message = "New password is mandatory")
-
private String password;
-
-
-
@ValidPassword
-
@NonNull
-
@NotBlank(message = "Confirm Password is mandatory")
-
private String confirmPassword;
-
}
-
-
两个重要的注释:
@PasswordValueMatch
:检查密码和确认密码是否匹配。@ValidPassword
:包含密码验证策略。
密码验证
密码验证涉及从规则集创建 a,它只是一个对象列表。注释是由PasswordValidator
Rule
@ValidPassword
PasswordConstraintValidator.class
-
package com.passay.sample.custompasswordvalidation.annotation;
-
-
-
-
import com.passay.sample.custompasswordvalidation.utils.PasswordConstraintValidator;
-
-
import javax.validation.Constraint;
-
import javax.validation.Payload;
-
import java.lang.annotation.Documented;
-
import java.lang.annotation.Retention;
-
import java.lang.annotation.Target;
-
-
import
static java.lang.annotation.ElementType.*;
-
import
static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-
-
/**
-
* <h2>ValidPassword</h2>
-
*
-
* @author aek
-
*/
-
@Documented
-
@Constraint(validatedBy = PasswordConstraintValidator.class)
-
@Target({ TYPE, FIELD, ANNOTATION_TYPE })
-
@Retention(RUNTIME)
-
public
@interface ValidPassword {
-
-
String
message
()
default
"Invalid Password";
-
-
Class<?>[] groups()
default {};
-
-
Class<?
extends
Payload>[] payload()
default {};
-
}
请考虑以下简单密码策略:
- 密码长度应在 8 到 16 个字符之间。
- 密码不应包含任何空格。
- 密码必须至少包含 1 个大写字符。
- 密码必须至少包含 1 个小写字符。
- 密码必须至少包含 1 位数字字符。
- 密码必须至少包含 1 个符号(特殊字符)。
- 拒绝包含按字母顺序排列的 >= 5 个字符序列的密码(例如 abcdef)。
- 拒绝包含 >= 5 个字符的数字序列(例如 12345)的密码。
该类包含所有以前定义的密码规则,而无需手动实现它们。PasswordConstraintValidator
-
package com.passay.sample.custompasswordvalidation.utils;
-
-
import com.passay.sample.custompasswordvalidation.annotation.ValidPassword;
-
import lombok.SneakyThrows;
-
import org.passay.*;
-
-
import javax.validation.ConstraintValidator;
-
import javax.validation.ConstraintValidatorContext;
-
import java.io.InputStream;
-
import java.util.Arrays;
-
import java.util.List;
-
import java.util.Properties;
-
-
-
/**
-
* <h2>PasswordConstraintValidator</h2>
-
*
-
* @author aek
-
*/
-
public
class
PasswordConstraintValidator
implements
ConstraintValidator<ValidPassword, String> {
-
-
@Override
-
public
void
initialize
(final ValidPassword arg0) {
-
-
}
-
-
@SneakyThrows
-
@Override
-
public
boolean
isValid
(String password, ConstraintValidatorContext context) {
-
-
//customizing validation messages
-
Properties
props
=
new
Properties();
-
InputStream
inputStream
= getClass()
-
.getClassLoader().getResourceAsStream(
"passay.properties");
-
props.load(inputStream);
-
MessageResolver
resolver
=
new
PropertiesMessageResolver(props);
-
-
PasswordValidator
validator
=
new
PasswordValidator(resolver, Arrays.asList(
-
-
// length between 8 and 16 characters
-
new
LengthRule(
8,
16),
-
-
// at least one upper-case character
-
new
CharacterRule(EnglishCharacterData.UpperCase,
1),
-
-
// at least one lower-case character
-
new
CharacterRule(EnglishCharacterData.LowerCase,
1),
-
-
// at least one digit character
-
new
CharacterRule(EnglishCharacterData.Digit,
1),
-
-
// at least one symbol (special character)
-
new
CharacterRule(EnglishCharacterData.Special,
1),
-
-
// no whitespace
-
new
WhitespaceRule(),
-
-
// rejects passwords that contain a sequence of >= 5 characters alphabetical (e.g. abcdef)
-
new
IllegalSequenceRule(EnglishSequenceData.Alphabetical,
5,
false),
-
// rejects passwords that contain a sequence of >= 5 characters numerical (e.g. 12345)
-
new
IllegalSequenceRule(EnglishSequenceData.Numerical,
5,
false)
-
));
-
-
RuleResult
result
= validator.validate(
new
PasswordData(password));
-
-
if (result.isValid()) {
-
return
true;
-
}
-
-
List<String> messages = validator.getMessages(result);
-
String
messageTemplate
= String.join(
",", messages);
-
context.buildConstraintViolationWithTemplate(messageTemplate)
-
.addConstraintViolation()
-
.disableDefaultConstraintViolation();
-
return
false;
-
}
-
-
}
Passay 列出了几个规则来帮助验证密码。可以使用Passay编写的规则的完整列表可以在官方网站上找到。
除了密码验证之外,passay 还允许您使用给定的策略生成密码。
创建以捕获将为数据验证引发的所有异常。BaseExceptionHandler.class
-
package com.passay.sample.custompasswordvalidation.web;
-
-
import lombok.extern.slf4j.Slf4j;
-
import org.springframework.http.HttpStatus;
-
import org.springframework.web.bind.MethodArgumentNotValidException;
-
import org.springframework.web.bind.annotation.ExceptionHandler;
-
import org.springframework.web.bind.annotation.ResponseStatus;
-
import org.springframework.web.bind.annotation.RestControllerAdvice;
-
-
import java.util.HashMap;
-
import java.util.Map;
-
-
@Slf4j
-
@RestControllerAdvice
-
public
class
BaseExceptionHandler {
-
-
-
@ResponseStatus(HttpStatus.BAD_REQUEST)
-
@ExceptionHandler(MethodArgumentNotValidException.class)
-
public ApiResponse
handleValidationExceptions
(MethodArgumentNotValidException ex) {
-
-
Map<String, String> errors =
new
HashMap<>();
-
-
ex.getBindingResult().getFieldErrors().forEach(error -> {
-
if (errors.containsKey(error.getField())) {
-
errors.put(error.getField(), String.format(
"%s, %s", errors.get(error.getField()), error.getDefaultMessage()));
-
}
else {
-
errors.put(error.getField(), error.getDefaultMessage());
-
}
-
}
-
);
-
return
new
ApiResponse(errors,
"VALIDATION_FAILED");
-
}
-
}
启动后端项目。http://localhost:8080/
在本文中,我创建了一个使用Angular作为前端的注册表单。
现在,使用命令行在文件夹下添加 Angular 项目:src/main
ng new webapp
添加注册表单代码的内容后。运行前端npm start
打开浏览器并输入无效的密码以验证验证是否正常工作。http://localhost:4200/
完整的源代码可以在我的GitHub 存储库中找到。
转载:https://blog.csdn.net/allway2/article/details/127776646