Multiple Regex #Pattern's for 1 Field? - regex

I was attempted to apply multiple #Pattern annotations to a single field:
#Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit.")
#Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter.")
#Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter.")
#Pattern(regexp = "(?=\S+$)", message = "Password must contain no whitespace.")
private String password;
However, I cannot do this. I want individual messages per violated regex constraint on the password field. Is this possible?
My alternative is to use JSF 2.0 f:validatorRegex tags.

You can use the inner #List annotation of #Pattern:
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter."),
#Pattern(regexp = "(?=\\S+$)", message = "Password must contain no whitespace.")
})
private String password;

Gunnar's solution won't work for me... '.+' in his regexp seem to be missing.
However, i'm using Michal's patternList and it works like a charm for me. (Play 2.3.x / Ebean-ORM)
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one upper letter."),
#Pattern(regexp = "(?=.*[!##$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
#Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
#Constraints.Required()
public String password1;

You might want to look into constraint composition. You would build one annotation per password constraint composed from the #Pattern annotation, and then finally build one composed annotation using the previously defined four. This would require no extra java code.
http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#validator-customconstraints-compound
Otherwise, build (with accompanying java code) a custom annotation called #PasswordValidator.
I tend to like composed validators, as it makes the purpose of the validation annotations clear on their purpose, instead of having many disjoint annotations.

I modified Gunnar answer and write composite constraint and this now seems to work correctly on 4 unit tests:
#NotNull
#Size(min=6, max=45)
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one uppercase letter."),
#Pattern(regexp = "(?=.*[!##$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
#Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
#Constraint(validatedBy = {}) // constraints composition
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
public #interface StrongPassword {
String message() default "Password doesn't match bean validation constraints.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

Related

How can I create strong passwords with FluentValidation?

I am designing a user registration screen using FluentValidation.
I want to establish a control mechanism that will provide information on all steps as follows.
The code I tried;
RuleFor(p => p.Password).Matches(#"[A-Z]+").WithMessage("Your password must contain at least one uppercase letter.");
RuleFor(p => p.Password).Matches(#"[a-z]+").WithMessage("Your password must contain at least one lowercase letter.");
RuleFor(p => p.Password).Matches(#"[0-9]+").WithMessage("Your password must contain at least one number.");
RuleFor(x => x.Password).Matches(#"[\!\?\*\.]*$").WithMessage("Your password must contain at least one (!? *.).");
But I could not reach the result I wanted. I also looked at the FluentValidation documentation but could not see any useful example.
I would be glad if you help.
Thank you.
Please refer to the following example:
public class Login
{
public string Password { get; set; }
}
public class PassWordValidator : AbstractValidator<Login>
{
public PassWordValidator()
{
RuleFor(p => p.Password).NotEmpty().WithMessage("Your password cannot be empty")
.MinimumLength(8).WithMessage("Your password length must be at least 8.")
.MaximumLength(16).WithMessage("Your password length must not exceed 16.")
.Matches(#"[A-Z]+").WithMessage("Your password must contain at least one uppercase letter.")
.Matches(#"[a-z]+").WithMessage("Your password must contain at least one lowercase letter.")
.Matches(#"[0-9]+").WithMessage("Your password must contain at least one number.")
.Matches(#"[\!\?\*\.]+").WithMessage("Your password must contain at least one (!? *.).");
}
}
Action:
[HttpPost]
public IActionResult TestPassword(Login model)
{
PassWordValidator _validator = new PassWordValidator();
var validResult = _validator.Validate(model);
if (!validResult.IsValid)
{
return BadRequest(validResult.Errors);
}
return Ok();
}
Here is the test result by postman:

Spring validation: regex annotation does not work

When executing the controller method I receive this log:
OBJECT: [Field error in object 'catalog' on field 'name': rejected value [safasf]; codes [Pattern.catalog.name,Pattern.name,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [catalog.name,name]; arguments []; default message [name],[Ljavax.validation.constraints.Pattern$Flag;#5f32f731,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute#2180fe7e]; default message [muss auf Ausdruck "[A-Za-z]" passen]]
Regex: [A-Za-z]
Input: safasf
The code:
...
#NotNull
#Size(min=1, max=8)
#Pattern(regexp = "[A-Za-z]")
private String name;
...
The controller:
#PostMapping(ADD_CATALOG)
public String addCatalog(#Valid #ModelAttribute Catalog catalog, BindingResult result){
if(result.hasErrors()){
logAction("addCatalog", "Validation of "+catalog.getName()+" failed: ", result.getAllErrors().toString());
return "redirect:/catalog/addCatalog/";
}
catalogProviderComponent.addOrUpdateCatalogEntity(catalogComponent.catalog2catalogEntity(catalog));
logAction("addCatalog","catalog", catalog);
return "redirect:/catalog/addCatalog/";
}
When I go to regex101.com everything seems to be fine. Beside that I tried few regex but none seem to work out properly.
To allow for one or more lowercase or uppercase letter, you should append + to the end of the pattern:
#NotNull
#Size(min=1, max=8)
#Pattern(regexp = "[A-Za-z]+")
private String name;

Knockout-Validation Using Regular Expression to Validate a password

Ive been wracking my head trying to get Knockout validation to do for password with at least 1 letter and least 1 number. Heres the code I think came closes with but still rule always fails.
self.Password.extend({ pattern: { message: "Password must have at least one number and one letter " }, params: "/^(?=.*[0-9]+.*)(?=.*[a-zA-Z]+.*)[0-9a-zA-Z]*$/" });
s
self.Password = ko.observable().extend({
pattern: {
message: "Password must have at least one number and one letter",
params: /^(?=.*[0-9])(?=.*[a-zA-Z])[A-Za-z0-9]+$/
}
});

Define Regular Expression Validation for custom DataType in MVC4

I upgraded a project from MVC3 to MVC4 and noticed that one of my validators wasn't triggering anymore. I chased it down to a custom DataType in the Shared/EditorTemplates folder that is used for capturing Social Security numbers in various forms across the site. (We only show the last 4 digits when the page is loaded after a save, to explain the regex.)
SSN.cshtml
#{
var ssn = (string)ViewData.TemplateInfo.FormattedModelValue;
if (!String.IsNullOrWhiteSpace(ssn)){
ssn = "###-##-" + Model.Substring(Model.Length - 4, 4);
}
}
#Html.TextBox("", ssn, new { #class = "text-box single-line ssn", pattern = #"^(\d{3}|###)-(\d{2}|##)-\d{4}$", placeholder = "###-##-####", title = "Expected pattern is ###-##-####" })
It seems like in MVC4 the unobtrusive validation wants to look for data-val-regex-pattern as an attribute of the rendered text box, not just pattern. Has anyone ran into this before?
Note: I'd like to keep the validation on the custom data type so I don't have to always remember to add it to each model.
Thanks!
You can have your own custom validator and put it in the model property. here is an example
public class SocialSecurityAttribute : RegularExpressionAttribute
{
public SocialSecurityAttribute () : base(#"^(\d{3}|###)-(\d{2}|##)-\d{4}$") { }
}
Then register it in the global asax.cs Application start as follows
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(SocialSecurityAttribute), typeof(RegularExpressionAttributeAdapter));
When you use it , it will be like any other built in attributes
[SocialSecurity(ErrorMessage ...)]
public string SocialSecurityNumber{get;set;}
I like implementing like this as the code can be reused . Otherwise you can just use RegularExpressionAttribute passsing the regex
I found out that in order to get MVC4 to render the correct data attributes to the input field, I'd need to replace the hyphens with underscores in the anonymous object passed to the TextBox helper. Here's the code that I ended up with:SSN.cshtml
#{
var ssn = (string)ViewData.TemplateInfo.FormattedModelValue;
if (!String.IsNullOrWhiteSpace(ssn) && ssn.Length == 11)
{
ssn = "###-##-" + Model.Substring(Model.Length - 4, 4);
}
else {
ssn = "";
}
}
#Html.TextBox("", ssn,
new
{
#class = "text-box single-line ssn",
data_val = "true",
data_val_regex_pattern = #"^(\d{3}|###)-(\d{2}|##)-\d{4}$",
data_val_regex = "Expected pattern is ###-##-####",
placeholder = "###-##-####"
}
)

VB.NET email validation with Regex

I've tried implementing a rather simple email validation function that seems return a false match even though the input is a valid email. I have searched for any issues with the existing regex but it seems to be correct.
Even though the match returns a false value the program is stepping to the next validation level (which it shouldn't).
Here is the email validation function.
Function EmailAddressChecker(ByVal emailAddress As String) As Boolean
Dim regExPattern As String = "^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$"
Dim emailAddressMatch As Match = Regex.Match(emailAddress, regExPattern)
If emailAddressMatch.Success Then
Return True
Else
Return False
End If
End Function
And for the form validation that calls upon the email validation function.
If (String.IsNullOrEmpty(EmailTextBox.Text) OrElse EmailAddressChecker(EmailTextBox.ToString)) Then
MessageBox.Show("Please enter a valid email addresss")
Return False
End If
The call for all of this happens on an click event which triggers a cascading serious of If statements checking to see if all the fields are set.
Skipping a large chunk of code the click event asks if "AreFieldsSet <> True". Inside of the "AreFieldsSet" function contains all the validation for multiple inputs; one of which is the email validation if statement.
Are the emails in UpperCase? If they aren't, they won't match.
If you want to modify the Regex so that it is Case insensitive, use this:
"^[a-zA-Z0-9._%+-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$"
To validate the email address you need to use the IsMatch function of the Regex object, it evaluate if the entry email address is valid.
Function EmailAddressChecker(ByVal emailAddress As String) As Boolean
Dim r As System.Text.RegularExpressions.Regex = Nothing
Dim regExPattern As String = "^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$"
If r.IsMatch(emailAddress ,regExPattern ) Then
Return True
Else
Return False
End If
End Function
You can try this code for your form validation If (String.IsNullOrEmpty(EmailTextBox.Text) OrElse EmailAddressChecker(EmailTextBox.ToString)<>true) Then
MessageBox.Show("Please enter a valid email addresss")
Return False
End If
Public Shared Function ValidEmailAddress(ByVal emailAddress As String, ByRef errorMessage As String) As Boolean
If emailAddress.IndexOf("#") > -1 Then
If (emailAddress.IndexOf(".", emailAddress.IndexOf("#")) > emailAddress.IndexOf("#")) AndAlso emailAddress.Split(".").Length > 0 AndAlso emailAddress.Split(".")(1) <> "" Then
errorMessage = ""
Return True
End If
End If
Return False
End Function