瑞典SSN正则表达式拒绝特定年龄以下的用户
本文关键字:用户 SSN 正则表达式 拒绝 瑞典 | 更新日期: 2023-09-27 18:13:10
我的正则表达式有问题。我已经使验证正确的瑞典社会安全号码以匹配这些标准成为可能。
- YYMMDDNNNN
- YYMMDD-NNNN
- YYYYMMDDNNNN
- YYYYMMDD-NNNN
但我也想拒绝用户注册,如果用户是18岁以下。我的正则表达式现在看起来是这样的:是否有人在瑞典社会安全号的年龄范围中遇到了同样的问题?
private const string RegExForValidation =
@"^('d{6}|'d{8})[-|('s)]{0,1}'d{4}$";
private const string RegExForValidation = @"^(?<date>'d{6}|'d{8})[-'s]?'d{4}$";
string date = Regex.Match("19970918-1234", RegExForValidation).Groups["date"].Value;
DateTime dt;
[Required(ErrorMessage = "Du måste ange personnummer")]
[RegularExpression(RegExForValidation, ErrorMessage = "Personnummer anges med 10 siffror (yymmddnnnn)")]
public string PersonalIdentityNumber { get; set; }
第二更新 public class ValidateOfAge : ValidationAttribute
{
public bool IsOfAge(DateTime birthdate)
{
DateTime today = DateTime.Today;
int age = today.Year - 18;
if (birthdate.AddYears(birthdate.Year) < today.AddYears(-age))
return false;
else
return true;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string RegExForValidation = @"^(?<date>'d{6}|'d{8})[-'s]?'d{4}$";
string date = Regex.Match((string)value, RegExForValidation).Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(date, new[] { "yyMMdd", "yyyyMMdd" }, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
if (IsOfAge(dt))
return ValidationResult.Success;
return new ValidationResult("Personnummer anges med 10 siffror (yymmddnnnn)");
}
}
在这种情况下,我不会使用正则表达式,而是依赖于基类库的内置DateTime解析功能:
public DateTime GetBirthDate(string ssn)
{
var strippedOfSerial =
ssn.Substring(0, ssn.Length - 4).TrimEnd('-');
return DateTime.ParseExact(
strippedOfSerial,
new[] { "yyMMdd", "yyyyMMdd" },
new CultureInfo("se-SE"),
DateTimeStyles.None);
}
现在您可以查看返回的DateTime
值,并将其与DateTime.Now
进行比较,以确定是否要拒绝它。
在我看来,这比依赖正则表达式更具可读性,并且可能更安全,更灵活。如你所知,你可以使用其他文化等来调整解析策略。
您需要从SSN获取出生日期,解析为DateTime,然后与今天的日期进行比较。
以下是检查一个人是否成年的方法:
public bool IsOfAge(DateTime birthdate)
{
DateTime today = DateTime.Today; // Calculating age...
int age = today.Year - birthdate.Year;
if (birthdate > today.AddYears(-age))
age--;
return age < 18 ? false : true; // If the age is 18+ > true, else false.
}
你可以这样使用:
string RegExForValidation = @"^(?<date>'d{6}|'d{8})[-'s]?'d{4}$";
string date = Regex.Match("19970918-1234", RegExForValidation).Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(date, new[] { "yyMMdd", "yyyyMMdd" }, new CultureInfo("sv-SE"), DateTimeStyles.None, out dt))
Console.WriteLine(IsOfAge(dt));
注意[-|('s)]
匹配-
、|
、(
、空格或)
。我确定您只想匹配连字符或空白。
我向正则表达式添加了一个命名捕获,并从字符类中删除了不必要的符号。另外,请注意{0,1}
与?
是相同的。
要让它在MVC应用中工作,你需要实现一个自定义验证器:
[Required(ErrorMessage = "Du måste ange personnummer")]
[ValidateOfAge] // <---------------------------- HERE
public string PersonalIdentityNumber { get; set; }
并按如下方式实现:
public class ValidateOfAge: ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string RegExForValidation = @"^(?<date>'d{6}|'d{8})[-'s]?'d{4}$";
string date = Regex.Match((string)value, RegExForValidation).Groups["date"].Value;
DateTime dt;
if (DateTime.TryParseExact(date, new[] { "yyMMdd", "yyyyMMdd" }, new CultureInfo("sv-SE"), DateTimeStyles.None, out dt))
if (IsOfAge(dt))
return ValidationResult.Success;
return new ValidationResult("Personnummer anges med 10 siffror (yymmddnnnn)");
}
}
不是做自定义RegEx,我建议查看可用的NuGet包,它能够解析有效的瑞典个人身份号码,然后提取诸如出生日期、年龄、性别等信息,这些信息可以用作验证的输入。方法.GetAge()
将与您的情况最相关。免责声明:我是该包的合著者之一。
使用SwedishPersonalIdentityNumber
实现ValidateOfAge
可能看起来像:
public class ValidateOfAge : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (SwedishPersonalIdentityNumber.TryParse((string)value, out var personalIdentityNumber))
{
if(personalIdentityNumber.GetAge() >= 18) {
return ValidationResult.Success;
} else {
return new ValidationResult("Du måste vara minst 18 år gammal.");
}
}
return new ValidationResult("Ogiltigt personnummer.");
}
}
SwedishPersonalIdentityNumber
支持你所描述的模式,包括一些有效的模式(例如,你知道PIN可以包含+吗?)
- 你可以在这里找到源代码:
- https://github.com/ActiveLogin/ActiveLogin.Identity
- NuGet上的包在这里:
- https://www.nuget.org/packages/ActiveLogin.Identity.Swedish/
- https://www.nuget.org/packages/ActiveLogin.Identity.Swedish.AspNetCore/
第二个包含一个验证属性,用于验证模型中的PIN。如果验证年龄的用例足够常见,我们可以将其实现到验证属性中。我创造了一个问题来找出兴趣和设计。
目前建议的API设计是这样的(针对您的场景):[SwedishPersonalIdentityNumber(MinimumAge = 18)]
public string PersonalIdentityNumber { get; set; }
如果这是你想看到的,请分享你的想法。