• Spring Boot 使用 Passay 库的自定义密码验证器


    许多在线网络平台要求用户在注册时输入强密码。此策略有助于减少用户数据对任何黑客攻击的脆弱性。

    在本文中,我们将创建一个带有注册页面的简单表单。在继续本教程之前,您应该对使用 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 依赖项以管理验证策略。

    1. <dependency>
    2. <groupId>org.passaygroupId>
    3. <artifactId>passayartifactId>
    4. <version>1.6.0version>
    5. dependency>


    您可以在此处找到所有版本。

    使用包含要验证的信息的类。UserData

    1. package com.passay.sample.custompasswordvalidation.model;
    2. import com.passay.sample.custompasswordvalidation.annotation.PasswordValueMatch;
    3. import com.passay.sample.custompasswordvalidation.annotation.ValidPassword;
    4. import lombok.*;
    5. import javax.validation.constraints.Email;
    6. import javax.validation.constraints.NotBlank;
    7. import javax.validation.constraints.NotEmpty;
    8. import javax.validation.constraints.NotNull;
    9. /**
    10. *

      UserData

    11. *
    12. * @author aek
    13. */
    14. @PasswordValueMatch.List({
    15. @PasswordValueMatch(
    16. field = "password",
    17. fieldMatch = "confirmPassword",
    18. message = "Passwords do not match!"
    19. )
    20. })
    21. @AllArgsConstructor
    22. @NoArgsConstructor
    23. @Getter
    24. @Setter
    25. @ToString
    26. public class UserData {
    27. @NonNull
    28. @NotBlank(message = "username is mandatory")
    29. private String username;
    30. @NotNull
    31. @NotEmpty
    32. @Email
    33. private String email;
    34. @ValidPassword
    35. @NonNull
    36. @NotBlank(message = "New password is mandatory")
    37. private String password;
    38. @ValidPassword
    39. @NonNull
    40. @NotBlank(message = "Confirm Password is mandatory")
    41. private String confirmPassword;
    42. }


    两个重要的注释:

    • @PasswordValueMatch:检查密码和确认密码是否匹配。
    • @ValidPassword:包含密码验证策略。

    密码验证

    密码验证涉及从规则集创建 a,它只是一个对象列表。注释是由PasswordValidatorRule@ValidPasswordPasswordConstraintValidator.class

    1. package com.passay.sample.custompasswordvalidation.annotation;
    2. import com.passay.sample.custompasswordvalidation.utils.PasswordConstraintValidator;
    3. import javax.validation.Constraint;
    4. import javax.validation.Payload;
    5. import java.lang.annotation.Documented;
    6. import java.lang.annotation.Retention;
    7. import java.lang.annotation.Target;
    8. import static java.lang.annotation.ElementType.*;
    9. import static java.lang.annotation.RetentionPolicy.RUNTIME;
    10. /**
    11. *

      ValidPassword

    12. *
    13. * @author aek
    14. */
    15. @Documented
    16. @Constraint(validatedBy = PasswordConstraintValidator.class)
    17. @Target({ TYPE, FIELD, ANNOTATION_TYPE })
    18. @Retention(RUNTIME)
    19. public @interface ValidPassword {
    20. String message() default "Invalid Password";
    21. Class[] groups() default {};
    22. Classextends Payload>[] payload() default {};
    23. }


    请考虑以下简单密码策略:

    • 密码长度应在 8 到 16 个字符之间。
    • 密码不应包含任何空格。
    • 密码必须至少包含 1 个大写字符。
    • 密码必须至少包含 1 个小写字符。
    • 密码必须至少包含 1 位数字字符。
    • 密码必须至少包含 1 个符号(特殊字符)。
    • 拒绝包含按字母顺序排列的 >= 5 个字符序列的密码(例如 abcdef)。
    • 拒绝包含 >= 5 个字符的数字序列(例如 12345)的密码。

    该类包含所有以前定义的密码规则,而无需手动实现它们。PasswordConstraintValidator

    1. package com.passay.sample.custompasswordvalidation.utils;
    2. import com.passay.sample.custompasswordvalidation.annotation.ValidPassword;
    3. import lombok.SneakyThrows;
    4. import org.passay.*;
    5. import javax.validation.ConstraintValidator;
    6. import javax.validation.ConstraintValidatorContext;
    7. import java.io.InputStream;
    8. import java.util.Arrays;
    9. import java.util.List;
    10. import java.util.Properties;
    11. /**
    12. *

      PasswordConstraintValidator

    13. *
    14. * @author aek
    15. */
    16. public class PasswordConstraintValidator implements ConstraintValidator {
    17. @Override
    18. public void initialize(final ValidPassword arg0) {
    19. }
    20. @SneakyThrows
    21. @Override
    22. public boolean isValid(String password, ConstraintValidatorContext context) {
    23. //customizing validation messages
    24. Properties props = new Properties();
    25. InputStream inputStream = getClass()
    26. .getClassLoader().getResourceAsStream("passay.properties");
    27. props.load(inputStream);
    28. MessageResolver resolver = new PropertiesMessageResolver(props);
    29. PasswordValidator validator = new PasswordValidator(resolver, Arrays.asList(
    30. // length between 8 and 16 characters
    31. new LengthRule(8, 16),
    32. // at least one upper-case character
    33. new CharacterRule(EnglishCharacterData.UpperCase, 1),
    34. // at least one lower-case character
    35. new CharacterRule(EnglishCharacterData.LowerCase, 1),
    36. // at least one digit character
    37. new CharacterRule(EnglishCharacterData.Digit, 1),
    38. // at least one symbol (special character)
    39. new CharacterRule(EnglishCharacterData.Special, 1),
    40. // no whitespace
    41. new WhitespaceRule(),
    42. // rejects passwords that contain a sequence of >= 5 characters alphabetical (e.g. abcdef)
    43. new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
    44. // rejects passwords that contain a sequence of >= 5 characters numerical (e.g. 12345)
    45. new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false)
    46. ));
    47. RuleResult result = validator.validate(new PasswordData(password));
    48. if (result.isValid()) {
    49. return true;
    50. }
    51. List messages = validator.getMessages(result);
    52. String messageTemplate = String.join(",", messages);
    53. context.buildConstraintViolationWithTemplate(messageTemplate)
    54. .addConstraintViolation()
    55. .disableDefaultConstraintViolation();
    56. return false;
    57. }
    58. }


    Passay 列出了几个规则来帮助验证密码。可以使用Passay编写的规则的完整列表可以在官方网站上找到。

    除了密码验证之外,passay 还允许您使用给定的策略生成密码。

    创建以捕获将为数据验证引发的所有异常。BaseExceptionHandler.class

    1. package com.passay.sample.custompasswordvalidation.web;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.http.HttpStatus;
    4. import org.springframework.web.bind.MethodArgumentNotValidException;
    5. import org.springframework.web.bind.annotation.ExceptionHandler;
    6. import org.springframework.web.bind.annotation.ResponseStatus;
    7. import org.springframework.web.bind.annotation.RestControllerAdvice;
    8. import java.util.HashMap;
    9. import java.util.Map;
    10. @Slf4j
    11. @RestControllerAdvice
    12. public class BaseExceptionHandler {
    13. @ResponseStatus(HttpStatus.BAD_REQUEST)
    14. @ExceptionHandler(MethodArgumentNotValidException.class)
    15. public ApiResponse handleValidationExceptions(MethodArgumentNotValidException ex) {
    16. Map errors = new HashMap<>();
    17. ex.getBindingResult().getFieldErrors().forEach(error -> {
    18. if (errors.containsKey(error.getField())) {
    19. errors.put(error.getField(), String.format("%s, %s", errors.get(error.getField()), error.getDefaultMessage()));
    20. } else {
    21. errors.put(error.getField(), error.getDefaultMessage());
    22. }
    23. }
    24. );
    25. return new ApiResponse(errors, "VALIDATION_FAILED");
    26. }
    27. }


    启动后端项目。http://localhost:8080/

    在本文中,我创建了一个使用Angular作为前端的注册表单。

    现在,使用命令行在文件夹下添加 Angular 项目:src/main

    ng new webapp

    添加注册表单代码的内容后。运行前端npm start

    打开浏览器并输入无效的密码以验证验证是否正常工作。http://localhost:4200/ 

    完整的源代码可以在我的GitHub 存储库中找到。

     

  • 相关阅读:
    简洁版用户登录系统
    网页乱码问题及其HTML编程解决方案
    Java之接口
    【SQL 初级语法 5】集合运算
    【Tailwind】footer固定底部
    Python入门自学进阶-Web框架——26、DjangoAdmin项目应用-数据记录操作
    Pytorch学习之路 - CNN
    【AIGC专题】Stable Diffusion 从入门到企业级实战0403
    深入理解element-wise add与concat特征图的连接方式
    SaaSBase:什么是JIRA?
  • 原文地址:https://blog.csdn.net/allway2/article/details/127776646