问题
The Problem
- I have a pre-defined
[StringLength()]
and[RegularExpression()]
constraint on my Code-First Model. - The
[StringLength()]
requirement is 8-16 characters - The
[RegularExpression()]
constraint for the password is in a different format from the encrypted password.- The password is encrypted before being shoved into the database.
- The encrypted password is 70 characters in length, which is higher than the 8-16 character limit defined in the Model.
- I am required to use
e.Encrypt()
, meaning I cannot use the default ASP.NET hashing algorithm.
I've searched high and low, but have yet to find the correct answer.
My Code
I have a function that allows a user to register an account. It looks like this:
[HttpPost]
public ActionResult Register([Bind(Include="Username,Password,EmailAddress")] UserModel user)
{
if (TryUpdateModel(user))
{
// Set password to a different format than Model's designated Regex
user.Password = e.Encrypt(user.Password);
context.Entry(user).State = EntityState.Added;
context.SaveChanges();
return RedirectToAction("Login", "Account");
}
return View();
}
In my UserModel.cs
file, I have the following constraints:
[Required]
[DataType(DataType.Password)]
[StringLength(16, MinimumLength = 8, ErrorMessage = "Must be between 8 and 16 characters.")]
[RegularExpression("^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]", ErrorMessage = ErrorMessage_PasswordRegex)]
public string Password { get; set; }
Again, the hashed password is in a completely different format. Therefore, I cannot update it because it throws a DbEntityValidationException
. This [RegularExpression()]
is for the format of the user's password. I need to be able to bypass or suspend the password's Regex constraint.
What I have done to remedy this
I've removed the [RegularExpression()]
requirements, and upped the [StringLength()]
to 70, which is the length of my password hash.
However, I don't want to allow users to input 70 characters of text. This seems like a cheap hack, and I feel that there should be a better way to do this. Any ideas?
回答1:
Here's an example:
We've got different requirements for user input than what our database requires. We might need more user input which we will programmatically act upon.
The EF model
public class UserModel()
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
[Required, StringLength(70)]
public string Password { get; set; }
}
Now here's the class we use to capture user input
public class UserViewModel()
{
[Required]
public string Name { get; set; }
[Required]
[RegularExpression("^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]", ErrorMessage = ErrorMessage_PasswordRegex)]
public string Password { get; set; }
[Required]
public string ConfirmPassword { get; set; }
}
Now we transform and map values.
The user won't know what to use for Id
and the database doesn't have need for ConfirmPassword
. We can also transform what the user originally entered as a password.
[HttpPost]
public ActionResult Register(UserViewModel model)
{
if ((ModelState.IsValid) &&
(model.Password == model.ConfirmPassword))
{
// map to EF model
var user = new UserModel
{
Name = model.Name,
Password = e.encrypt(model.Password) // transform, encrypt, whatever
};
db.Users.Add(user); // use EF model to persist
...
return RedirectToAction("Login", "Account");
}
return(model);
}
来源:https://stackoverflow.com/questions/29566422/how-do-i-update-a-password-thats-in-a-different-format-from-the-defined-model