FluentValidator自定义密码在第一条规则处停止



我在MVC项目中使用FluentValidator来验证视图模型密码,所以这是我的类:

namespace example123.Models
{
public class RegisterModel
{
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
public class RegisterValidator : AbstractValidator<RegisterModel>
{
public RegisterValidator()
{
RuleFor(x => x.Email)
.NotNull()
.NotEmpty()
.WithMessage("Email is required")
.EmailAddress()
.WithMessage("Invalid email format");
RuleFor(a => a.Password).Password();
}
}
}

因此,我创建了一个自定义规则,并用扩展了该规则

public static class RuleBuilderExtensions
{
public static IRuleBuilder<T, string> Password<T>(this IRuleBuilder<T, string> ruleBuilder, int minimumLength = 8)
{
var options = ruleBuilder
.NotEmpty().WithMessage("Required")
.MinimumLength(minimumLength).WithMessage("Length")
.Matches("[A-Z]").WithMessage("Uppercase msg")
.Matches("[a-z]").WithMessage("Lowercase msg")
.Matches("[0-9]").WithMessage("Digit msg")
.Matches("[^a-zA-Z0-9]").WithMessage("Sepcial char msg");
return options;
}
}

呈现的Html代码:

<input type="password" class="form-control input-validation-error validate-equalTo-blur" autocomplete="current-password" aria-required="true" data-val="true" data-val-minlength="Password must be at least 6 characters long" data-val-minlength-min="6" data-val-regex="Uppercase" data-val-regex-pattern="[A-Z]" data-val-required="Password is required" id="Password" name="Password" aria-describedby="Password-error" aria-invalid="true">

视图Register.cs.html使用默认的jQuery validate实现,该实现来自默认的MVC项目。电子邮件工作正常,但密码停止在";大写";rule[A-Z]并且不会消失,则不会显示其他自定义消息。知道为什么吗?

因此,我提供了一系列可能满足您需求的不同选项。

您是否反对使用FluentValidation的Must方法?如果是这样的话,它可以看起来像这样:

创建验证方法:

private bool ValidatePassword(string pw)
{
var lowercase = new Regex("[a-z]+");
var uppercase = new Regex("[A-Z]+");
var digit = new Regex("(\d)+");
var symbol = new Regex("(\W)+");
return (lowercase.IsMatch(pw) && uppercase.IsMatch(pw) && digit.IsMatch(pw) && symbol.IsMatch(pw));
}

然后创建您发送电子邮件的规则。

RuleFor(x => x.Password)
.Length(5, 15)
.Must(HasValidPassword);
}

如果你有一个确认密码字段,你也可以这样做:

RuleFor(x => x.ConfirmPassword)
.Equal(x => x.Password)
.WithMessage("Passwords must match");

我认为主要的问题是,你在一个扩展中这样做,fluentvalidation可以考虑自定义而不是内置的,所以它可能会遇到一些问题。

我注意到的另一件事是你可以尝试改变:

.Matches("[A-Z]").WithMessage("Uppercase msg")

.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 (!? *.).");

我添加了正则表达式的@和+。这可能对你也有帮助。

不确定fluentvalidation是否关心加号,但试着把它从扩展方法中去掉,像对待电子邮件一样做一个正常的规则,看看这是否能解决问题。

如果您正在尝试进行客户端验证,那么我确信这不会起作用。我认为目前的方法是用于服务器端验证,而不是客户端验证。您也可以直接在客户端中使用jQuery,这可能会满足您对clien端的需求。这里有一个快速的例子:

jQuery.validator.addMethod("passwordCheck",
function(value, element, param) {
if (this.optional(element)) {
return true;
} else if (!/[A-Z]/.test(value)) {
return false;
} else if (!/[a-z]/.test(value)) {
return false;
} else if (!/[0-9]/.test(value)) {
return false;
}
return true;
},
"error msg here");

然后将其附加到视图中的属性:

<input type="password" id="RegisterModel_Password" 
name="RegisterModel.Password" 
class="form-control" 
required="required" minlength="8" 
passwordCheck="passwordCheck"/>

我复制了您的代码并编写了以下小xUnit测试:

[Theory]
[InlineData("hello", false)]
[InlineData("helloworld", false)]
[InlineData("HelloWorld", false)]
[InlineData("HelloWorld1", false)]
[InlineData("HelloWorld1!", true)]
public void TestName(string password, bool expectedValidity)
{
// Arrange
var testee = new RegisterValidator();
// Act
var result = testee.Validate(new RegisterModel{Email = "bla@blub.com", Password = password});
// Assert
result.IsValid.Should().Be(expectedValidity);
}

我的机器上所有的测试都通过了。那么,你能检查一下你的机器上是否有一个测试用例失败了吗?否则,客户端逻辑一定有问题(例如,缺少刷新(。

最新更新