将输入密码与散列密码进行比较,验证错误C#MVC

时间:2015-10-27 20:59:23

标签: c# model-view-controller hash passwords salt

我正在尝试创建一个表单来注册新用户并使用MVC模式将数据保存到Entity Framework中;问题是我试图比较输入的密码如下(代码写在模型中)

[Required(ErrorMessage = "Enter Password!")]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string tPassword { get; set; }

[DataType(DataType.Password)]
[Compare("tPassword", ErrorMessage = "The password and confirmation password does not match.")]
public string Confirmpassword { get; set; }

下一步是对密码进行哈希并保存(我使用以下方法创建了一个名为Security的新类,以及其他验证密码的方法),以下是代码:

public static void HashAndSavePassword(string password, RegisterTable usr)
{
    var v = new Rfc2898DeriveBytes(password, 16, 3987);
    usr.tPassword = Convert.ToBase64String(v.GetBytes(25), Base64FormattingOptions.None);
    usr.Salt = Convert.ToBase64String(v.Salt, Base64FormattingOptions.None);
}

然后在控制器中我使用以下来调用负责密码散列的方法,然后将用户数据保存到Entity Framework中:

public ActionResult Register(RegisterTable user)
{
    if (ModelState.IsValid)
    {
         // To check if username already exist
         var searchUserName = db.RegisterTables.Where(x => x.tUserName.Equals(user.tUserName)).FirstOrDefault();

         if (searchUserName == null)
         {
             Security.HashAndSavePassword(user.tPassword, user);

             db.RegisterTables.Add(user);
             db.SaveChanges();
             ModelState.Clear();
             return RedirectToAction("Login");
         }
         else ModelState.AddModelError("", "User is already Registred.");            
     }

     return View(user);
 }

问题是我在运行代码时遇到以下错误:

enter image description here

但是如果删除这一行,代码将正常工作:

[Compare("tPassword", ErrorMessage = "The password and confirmation password does not match.")]

任何人都可以向我解释为什么会发生这种情况以及如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您在DbContext上将ValidateOnSaveEnabled设置为true

context.Configuration.ValidateOnSaveEnabled = true;

这意味着您的验证将执行两次。首先是模型绑定器(由MVC完成) - 这不会引发错误,因为两个密码都是相同的。但是在你的HashAndSavePassword中你有纯文本的ConfirmPassword和散列形式的tPassword。因此,当您调用save时,EF将抛出错误。

你可以:

  1. 通过将ValidateOnSaveEnabled设置为false来关闭EF模型验证。
  2. 在HashAndSavePassword函数中也散列了ConfirmPassword属性(这是黑客攻击)
  3. 使用不同的模型,然后转换为EF中使用的模型。 (这是提到的)
  4. 您的数据库模型

    public class RegisterTable
    {
        public int Id { get; set; }
        public string tPassword { get; set; }
        public string tUserName { get; set; }
        public string Salt { get; set; }
    
        ...
    }
    

    您的观看模型:

    public class RegisterModel
    {
        // put username validation rules here
        public string UserName { get; set; }
    
        [Required(ErrorMessage = "Enter Password!")]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    
        [DataType(DataType.Password)]
        [Compare("Password", ErrorMessage = "The password and confirmation password does not match.")]
        public string Confirmpassword { get; set; }
    
        ...
    
        public RegisterTable Map()
        {
            var v = new Rfc2898DeriveBytes(this.Password, 16, 3987);
            return new RegisterTable()
            {
    
                Salt = Convert.ToBase64String(v.Salt, Base64FormattingOptions.None),
                tPassword = Convert.ToBase64String(v.GetBytes(25), Base64FormattingOptions.None),
                tUserName = this.UserName
            };
        }
    }
    

    你的行动

    public ActionResult Register(RegisterModel user)
    {
        if (ModelState.IsValid)
        {
            // To check if username already exist
            var searchUserName = db.RegisterTables.Where(x => x.tUserName.Equals(user.UserName)).FirstOrDefault();
    
            if (searchUserName == null)
            {
                var dbUser = user.Map();
    
                db.RegisterTables.Add(user);
                db.SaveChanges();
                ModelState.Clear();
                return RedirectToAction("Login");
            }
            else ModelState.AddModelError("", "User is already Registred.");
        }
    
        return View(user);
    }