As I explored in the debugger, it turned out that the incoming object is processed in the following order:
- Spring performs a bean check on JSON deserialization in
SpringValidatorAdapter::validate . The password here is in plain text. @HandleBeforeCreate is called and the password is hashed.- JPA authenticates the object before saving to the database. The password here is already hashed, and verification is not performed. In my case (Hibernate JPA implementation) the validation was done in
BeanValidationEventListener::validate .
Solution 1 (full check in both phases)
One solution I found was to loosen the restriction in the password field by simply using @NotEmpty (so that both phases of the check went through and still the incoming JSON was checked for void / invalidity) and do a raw password size check in @HandleBeforeCreate (and when need to discard the corresponding exception).
The problem with this solution is that it required me to write my own exception handler. In order to keep up with the high standards set by Spring Data REST regarding the body of the error response, I would have to write a lot of code for this simple case. A way to do this is described here .
Solution 2 (Spring bean validation without JPA entity validation)
As outlined by Bohuslav Burghardt , you can disable the second stage of verification performed by JPA. This way you can keep the min and max restrictions and at the same time avoid writing extra code. As always, this is a compromise between simplicity and security. The way to disable JPA is described here .
Solution 3 (maintaining the restriction of only the minimum password length)
Another solution, at least in my case, was to leave the maximum password length unlimited. Thus, at the first stage of the check, the password was checked whether it was not too short, and in the second phase it is checked every time (since the encrypted password is already quite long).
The only caveat for this solution is that @Size(min = 5) doesn't seem to check for nullity, so I had to add @NotNull to handle this case. In general, the field is annotated as:
@NotNull @Size(min = 5) private String password;
Wojtek
source share