Проверка пароля и подтверждение пароля Spring Boot

В настоящее время я тестирую API своего весеннего загрузочного приложения с помощью Swagger, и когда я ввожу несоответствующие пароли или даже пароль с размером, выходящим за пределы (min = 5 и max = 15) размера, я не получаю 404 код ошибки, когда он ожидается. Другие ошибки для других переменных объекта правильно обнаруживаются, но, по-видимому, ничего для пароля. Что может быть неправильным для совпадения plainPassword и RepeatPassword в моем объекте ниже? Поскольку аннотация @PasswordMatch, похоже, не выполняет работу, которую я ожидаю от сравнения простого пароля и повторного пароля.

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import com.bcore.hw.validation.PasswordMatch;
import lombok.NoArgsConstructor;
import lombok.Data;


@Entity
@Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
@PasswordMatch(message = "{register.repeatPassword.mismatch}")
@NoArgsConstructor
@Data
public class SiteUser {
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long userId;

    @Column(name = "email", unique=true)
    @Email(message = "{register.email.invalid}")
    @NotBlank(message = "{register.email.invalid}")
    private String email;
    
    @Transient // meaning it will not be saved in DB
    @Size(min=5, max=15, message = "{register.password.size}")
    private String plainPassword; //unencrytped
    
    @Transient
    private String repeatPassword;

    @Column(name = "password", length=60)
    private String password;

    @Column(name = "role", length=20)
    private String role;
    
    @Column(name = "enabled")
    private Boolean enabled = false;
    
    public void setPlainPassword(String plainPassword) {
        //System.out.println("PASSWORD BEFORE " + plainPassword);
        this.password = new BCryptPasswordEncoder().encode(plainPassword);
        //System.out.println("HERE IS PASSWORD" + this.password + "PASSWORD LENGTH = " + (this.password).length());
        this.plainPassword = plainPassword;
    }

}

Обновлено с помощью пользовательского валидатора:

Итак, теперь у меня есть PasswordMatch.java и PasswordMatchValidator.java, но у меня есть небольшая путаница в отношении того, как настроить аннотации @PrePersist и @PreUpdate в сущности:

package com.bcore.hw.validation;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target(TYPE)
@Retention(RUNTIME)
@Constraint(validatedBy=PasswordMatchValidator.class)
@Documented
public @interface PasswordMatch {
    String message() default "{error.password.mismatch}";
    
    Class<?>[] groups() default {};
    
    Class<? extends Payload>[] payload() default {};
}



package com.bcore.hw.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import com.bcore.hw.model.SiteUser;

public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, SiteUser>{

    @Override
    public void initialize(PasswordMatch p) {
        
    }
    
    public boolean isValid(SiteUser user, ConstraintValidatorContext c) {
        String plainPassword = user.getPlainPassword();
        String repeatPassword = user.getRepeatPassword();
        
        if (plainPassword == null || !plainPassword.equals(repeatPassword)) {
            return false;
        }
        
        return true;
    }

}

В настоящее время в сущности вы можете видеть @PasswordMatch перед определением класса, но это не работает. Итак, @PrePersist и @PreUpdate используются только для определений методов сущности, но какой метод я бы поместил под них? Вызов метода isValid() из интерфейса PasswordMatch? Не совсем уверен, что делать в сущности в этот момент.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
9 395
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже этот баг в открытом статусе из-за поля @Transient

Аааа да вот в чем дело. Таким образом, удаление аннотации @Transient позволяет выполнить проверку, но похоже, что нет обходного пути, чтобы атрибут фактически не сохранялся в БД (?)

CDA the Programmer 21.12.2020 23:08

Вы можете реализовать свою пользовательскую аннотацию для проверки, а затем обрабатывать элементы с пользовательскими аннотациями в прослушивателе prePersist/preUpdate гибернации.

Dmitriy Mishenyov 21.12.2020 23:29

Итак, на данный момент я определил классы PasswordMatch и PasswordMatchValidator, которые вы можете увидеть в моих правках выше. Теперь мой вопрос заключается в том, как использовать PrePersist и PreUpdate в объекте, чтобы заставить работать метод isValid(), потому что на данный момент, хотя у меня есть PasswordMatch, определенный для объекта, он все еще не работает.

CDA the Programmer 22.12.2020 17:24
@PostMapping("/change-password")
public String changePassword(@RequestParam("newPassword") String newPassword,
        @RequestParam("confirmNewPassword") String confirmNewPassword, Model model, HttpSession session) {

    model.addAttribute("title", "Change Password Form");

    String email = (String) session.getAttribute("email");
    UserEntity userEntity = userRepository.getUserByUserName(email);
    if (newPassword.equals(confirmNewPassword)) {
        userEntity.setPassword(bCryptPasswordEncoder.encode(newPassword));
        userRepository.save(userEntity);
        return "redirect:/signin?change=Password Changed Successfully";
    } else {
        session.setAttribute("message", "Password doesn't matched !!");
        return "password_change_form";
    }

}

Другие вопросы по теме