2015-10-27 3 views
0

Я пытаюсь создать форму для регистрации нового пользователя и сохранения данных в Entity Framework с использованием шаблона MVC; дело в том, что я пытаюсь сравнить введенный пароль следующим образом (код записывается в модели)Сравните введенный пароль с хешированным паролем, ошибка проверки C# MVC

[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; } 

Следующим шагом является хэш пароля и сохранить его (я создал новый класс безопасности с следующий метод и другие методы для проверки пароля), Ниже приводится код:

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

Вы ValidateOnSaveEnabled значение ИСТИНА на вашем DbContext

context.Configuration.ValidateOnSaveEnabled = true; 

Это означает, что проверка будет выполняться дважды. Сначала с помощью связующего устройства (сделанного MVC) - это не приведет к ошибке, потому что оба пароля одинаковы. Но тогда в вашем HashAndSavePassword у вас есть ConfirmPassword в виде обычного текста и tPassword в хэш-форме. Таким образом, EF будет вызывать ошибку при вызове save.

Вы можете:

  1. выключают проверки модели EF, установив ValidateOnSaveEnabled ложь.
  2. в функции HashAndSavePassword также hash свойство ConfirmPassword (это взломать)
  3. использовать другую модель в действии, а затем преобразовать в модель, используемую в EF. (Это называется)

Ваша модель DB

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); 
} 
+0

Спасибо, что он работает, но я не понял третьего пункта, что вы подразумеваете под преобразованием модели в модель EF, можете ли вы предоставить дополнительную информацию или хорошие учебники, которые объясняют это? Еще раз спасибо – moji

+0

Теперь вы используете класс RegisterTable в качестве параметра в действии Register. Это обычно не очень хорошая идея, потому что ваша модель БД будет иметь другой набор свойств, чем ваша форма регистрации.Например: нет необходимости иметь поле ConfirmPassword в вашей модели БД, потому что вам не нужно хранить это в БД. И ваша модель БД будет иметь свойства, которые никогда не должны подвергаться просмотру (например, IsDeleted, DateModified, ...). Поэтому лучше иметь модель, которая описывает вашу форму представления, проверять эту модель, а затем преобразовывать ее в другую модель БД или сервисную модель. – longchiwen

+0

Я получил ур точку, спасибо ... Но я до сих пор не знаю, как конвертировать в DB .. – moji

Смежные вопросы