Spring Boot匹配密码验证错误显示

问题描述 投票:0回答:1

我自己的验证密码输入的注释有问题。正如我测试的那样,当密码匹配时,注册确实有效,但当密码不匹配时,我想将它们显示在我的 /register 端点/站点中,就像所有其他有效的注释一样。 为什么我的密码匹配错误没有显示在 register.html 上?

注册.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" href="assets/css/form-style.css">
    <title>Register</title>
</head>
<body>
    <div th:replace="~{header :: header}">...</div>
    <h1>Register</h1>

    <form th:action="@{/createUser}" th:object="${MyUser}" method="post">
        <div th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="errors"></div>
        <input type="text" th:field="*{email}" placeholder="email"><br>

        <div th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="errors"></div>
        <input type="password" th:field="*{password}" placeholder="password"><br>
        **//This should display the error**
        **<div th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}" class="errors"></div>**
        <input type="password" th:field="*{confirmPassword}" placeholder="confirm password"><br>

        <div th:if="${#fields.hasErrors('age')}" th:errors="*{age}" class="errors"></div>
        <input type="number" th:field="*{age}" placeholder="age"><br>
        <input type="submit" value="Register"> <br>
    </form>

    <div th:replace="~{footer :: footer}">...</div>
</body>
</html>

MyUser.java

package com.loginthyme.security.model;

import com.loginthyme.security.annotation.FieldsValueMatch;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Set;

@Document(collection = "users")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@FieldsValueMatch.List({@FieldsValueMatch(field = "password", fieldMatch = "confirmPassword", message = "The password fields must match")}
)
public class MyUser {
    @Id
    private ObjectId id;
    @NotEmpty(message = "Email can not be empty")
    @Email(message = "Invalid email format")
    private String email;
    @NotEmpty(message = "Password can not be empty")
    private String password;
//    @Transient
    private String confirmPassword;
    @Min(value = 18, message = "Age must be at least 18")
    @NotNull(message = "Age can not be empty")
    private Integer age;
    private Set<Role> role;
}

FieldsValueMatchValidator.java

package com.loginthyme.security.validations;

import com.loginthyme.security.annotation.FieldsValueMatch;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.beans.BeanWrapperImpl;

public class FieldsValueMatchValidator implements ConstraintValidator<FieldsValueMatch, Object> {
    private String field;
    private String fieldMatch;

    @Override
    public void initialize(FieldsValueMatch constraintAnnotation) {
        this.field = constraintAnnotation.field();
        this.fieldMatch = constraintAnnotation.fieldMatch();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        Object fieldValue = new BeanWrapperImpl(value).getPropertyValue(field);
        Object fieldMatchValue = new BeanWrapperImpl(value).getPropertyValue(fieldMatch);
        if (fieldValue != null) {
            return fieldValue.equals(fieldMatchValue);
        } else {
            return fieldMatchValue == null;
        }
    }
}

FieldsValueMatch.java

package com.loginthyme.security.annotation;

import com.loginthyme.security.validations.FieldsValueMatchValidator;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.*;

@Constraint(validatedBy = FieldsValueMatchValidator.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsValueMatch {
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    String message() default "Fields value don`t match";
    String field();
    String fieldMatch();

    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @interface List {
        FieldsValueMatch[] value();
    }
}

RegisterController.java

package com.loginthyme.security.controller;

import com.loginthyme.security.model.MyUser;
import com.loginthyme.security.model.Role;
import com.loginthyme.security.repository.UserRepository;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.Collections;

@Controller
@Slf4j
public class RegisterController {
    UserRepository userRepository;
    PasswordEncoder passwordEncoder;

    @Autowired
    public RegisterController(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @PostMapping("/createUser")
    public String createUser(@Valid @ModelAttribute("MyUser") MyUser myUser, BindingResult bindingResult) {
        if(bindingResult.hasErrors()) {
            return "register";
        }
        if(!userRepository.existsByEmail(myUser.getEmail())) {
            myUser.setPassword(passwordEncoder.encode(myUser.getPassword()));
            myUser.setRole(Collections.singleton(Role.ROLE_USER));
            userRepository.save(myUser);
            log.info("User succesfully registered");
        } else {
            log.info("Such a user already exists");
        }
        return "redirect:/register";
    }

    @GetMapping("/register")
    public String displayRegisterPage(Model model) {
        model.addAttribute("MyUser", new MyUser());
        return "register";
    }
}
spring-boot validation thymeleaf
1个回答
0
投票

您的 Thymeleaf 模板中似乎缺少确认密码字段的错误消息。您已在 MyUser 类中正确添加了验证注释,但您需要在 HTML 模板中处理错误消息。

在您的register.html 文件中,确保为confirmPassword 字段添加错误消息,类似于您为电子邮件和密码字段所做的操作。修改方法如下:

<div th:if="${#fields.hasErrors('confirmPassword')}" th:errors="*{confirmPassword}" class="errors"></div> 

当验证失败时,此行将显示confirmPassword字段的错误消息。确保将其放置在密码确认输入字段所在的表单部分中。

© www.soinside.com 2019 - 2024. All rights reserved.