I need password validation (for example a password must contain at least 4 chars, max 8 and min 1 numeric digit).
I have model (of course with getters and setters):
#Entity
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 5534441879591858724L;
#Id
#GeneratedValue
private long id;
#NotBlank
#Email
private String email;
#Pattern(regexp = "^(?=.*\\d).{4,8}$", flags = Flag.UNICODE_CASE)
private String password;
#NotBlank
#Size(min=2, max=30)
private String name;
I'm catching ConstraintViolationException during saving user info to database and use informations from this exception to inform the user during registration what fields must be corrected because of invalid length etc.
Everything is ok with validation, but not with password. I checked regex expression out of this model class and it works ok, but when i put this regex into annotation parameter ( #Pattern(regexp = "^(?=.*\\d).{4,8}$", flags = Flag.UNICODE_CASE)) it doesn't work and I have an error:
HHH000346: Error during managed flush [Validation failed for classes
[pl.rpf.kingdom.models.User] during persist time for groups
[javax.validation.groups.Default, ] List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must match "^(?=.*\d).{4,8}$"', propertyPath=password, rootBeanClass=class
pl.rpf.kingdom.models.User,
messageTemplate='{javax.validation.constraints.Pattern.message}'} ]]
Please help me with understanding this error and maybe you have some idea how to solve this problem.
Problem was with password encrypting, I forgot about it.
Regex matches mathod was always false, because it was trying to compare password after encrypting.
I solved problem by putting validation out of model class, before password encrypting.
Other way to resolve problem could be using spring #Valid annotation to validate form before trying save it to database (in my situation it could be problematic from other cases).
Related
I am writing a spring boot application which depends on spring-boot-starter-data-mongodb and spring-boot-starter-validation. Following class with a self reference is stored in a Mongodb collection (simplified):
#Data
#Accessors(fluent = true, chain = true)
#Document
public class User {
#Id #NotBlank
private String username;
#NotBlank #Email
private String mail;
private String customerNo;
#DBRef
private User superior; // <== reference to another user document
}
Either #DBRef or #DocumentReference work great with the field superior. Also simple validations with annotation like #NotBlank or #Email are working.
But I noticed that it is possible to store a user, whose superior user does not exist in the mongo collection. Is there a validator that can check that? If not, what is the proper way to make sure only valid data is stored?
I am trying to apply a #NotBlank validation to a class field. That field has also the #JsonProperty annotation:
#JsonProperty("ID")
#NotBlank(message = "ID must not be blank")
private String id;
When I pass "" or " " to the property and the incoming JSON field is named "ID" in capital letters then I do not see the expected constraint violation. If it is named "id" in lower case, then the JSON validation works properly.
However, in reality the JSON will come from the requester side in capital letters. So, I cannot simply remove #JsonProperty. Is there a way to solve this problem?
What is the difference between the validation check of the following three fields?
#Entity
public class MyEntity {
#Column(name = "MY_FIELD_1", length=13)
private String myField1;
#Column(name = "MY_FIELD_2")
#Size(min = 13, max = 13)
private String myField2;
#Column(name = "MY_FIELD_3")
#Length(min = 13, max = 13)
private String myField3;
// getter & setter
}
I read that the first one has to do with DDL stuff.
The second is for bean-validation.
The third is for hibernate-validation.
Is that correct? What I still don't understand is: When do I have to use which one? When does one of these annotations trigger?
Edit: Think of the following situation:
Given the requirement to develope an entity with a field of type string with length 13. Which of above mentioned methods would you choose? Or even better: Which questions do you have to ask yourself to find out which one suits your purposes?
#Column is a JPA annotation and the length attribute is used by the schema generation tool to set the associated SQL column length.
#Size is a Bean Validation annotation that validates that the associated String has a value whose length is bounded by the minimum and maximum values.
#Length is a Hibernate-specific annotation and has the same meaning as #Size
So both 2. and 3. should validate the String length using Bean Validation. I'd pick 2. because it's generic.
I'm using Spring Boot Data REST to persist my User entities
#Entity
public class User {
#Id
#GeneratedValue
private long id;
#NotEmpty
private String firstName;
#NotEmpty
private String lastName;
#NotEmpty
private String email;
#Size(min = 5, max = 20)
private String password;
// getters and setters
}
using the repository:
public interface UserRepository extends CrudRepository<User, Long> {}
What I want to do is validate the POSTed users first:
#Configuration
public class CustomRestConfiguration extends SpringBootRepositoryRestMvcConfiguration {
#Autowired
private Validator validator;
#Override
protected void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", validator);
}
}
and only later hash the user's password before storing it in the DB:
#Component
#RepositoryEventHandler(User.class)
public class UserRepositoryEventHandler {
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
#HandleBeforeCreate
public void handleUserCreate(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
}
}
As it turns out though, validation is performed after the password hashing and as a result it fails due to the hashed password being too long.
Is there any way to instruct Spring to perform validation first and only then hash the password? I know I could write a controller myself and specify everything in a fine-grained manner, but I'd rather leave it as my last resort.
As I investigated in the debugger it turned out that an incoming entity is processed in the following order:
Spring performs bean validation when deserializing JSON in SpringValidatorAdapter::validate. The password here is in plain text.
#HandleBeforeCreate is invoked and the password is hashed.
JPA performs entity validation before saving it in the DB. The password here is already hashed and validation fails. In my case (Hibernate implementation of JPA) the validation was performed in BeanValidationEventListener::validate.
Solution 1 (full validation in both phases)
One solution I found was to relax the constraint on the password field by just using #NotEmpty (so that both validation phases passed and still the incoming JSON was checked for emptiness/nullity) and perform the size validation of the raw password in #HandleBeforeCreate (and throw appropriate exception from there if needed).
The problem with this solution is that it required me to write my own exception handler. To keep up with the high standards set by Spring Data REST with respect to error response body, I would have to write lots of code for this one simple case. The way to do this is described here.
Solution 2 (Spring bean validation without JPA entity validation)
As hinted by Bohuslav Burghardt, it is possible to disable the second validation phase done by JPA. This way you can keep the min and max constrains and at the same time avoid writing any additional code. As always it's a trade-off between simplicity and safety. The way to disable JPA is described here.
Solution 3 (preserving only min password length constraint)
Another solution, at least valid in my case, was to leave the max password length unbounded. This way in the first validation phase the password was checked whether it wasn't too short and in the second phase it effectively validated every time (because encrypted password was already long enough).
The only caveat to this solution is that #Size(min = 5) does not seem to check for nullity so I had to add #NotNull to handle this case. All in all the field is annotated as:
#NotNull
#Size(min = 5)
private String password;
I currently galley with data validation via Hibernate. Especially with the #Pattern annotation
Wholesale verification is always false, no matter what I do, so I can not save the object.
I try this, among other things:
#NotNull
#Size(max=30)
#SafeHtml
#Pattern(regexp="[a-zA-Z]", messsage="the name can only contain letters")
private String name;
et ceci :
#NotNull
#Size(max=30)
#SafeHtml
#Pattern(regexp="\\D", messsage="the name can only contain letters")
private String name;
In both case, if i write "toto," I have the error message that appears.
Someone an idea?
Have you tried [a-zA-Z]*
The patterns you have look like they only capture one letter. You need a * or a + to suggest multiple letters.