Какая часть приложения должна отвечать за хеширование пароля пользователя? - PullRequest
0 голосов
/ 16 января 2010

Я пишу приложение ASP.NET MVC, которое обеспечит функциональность регистрации пользователей, но я не уверен, какая часть приложения (например, объект модели User Domain, Controller, ViewModelMappers) должна отвечать за хеширование пароля пользователя. У меня есть страница регистрации, которая использует строго типизированную ViewModel и действие Register в моем UserController, как показано ниже:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(UserRegisterViewModel userRegisterViewModel)
{
    var user = userViewModelMapper.Map(userRegisterViewModel);
    INotification validationResult = user.ValidateForRegistration(userRepository);

    if (!validationResult.HasErrors)
    {
        user.HashPassword();
        userRepository.AddOrUpdate(user); // i'm using NHibernate
        return View("RegistrationAcknowledgement");
    }

    foreach (IError error in validationResult.Errors)
        ModelState.AddModelError(error.Property, error.Message);

    ViewData["country"] = new SelectList(countryRepository.GetAll(), "Code", "Name", userRegisterViewModel.Country);
    return View("RegistrationForm", userRegisterViewModel);
}

Пользовательские объекты частично составлены объектами LoginDetail, как показано, и чтобы не подвергать внутренности объекта User сверх того, что абсолютно необходимо, свойство Password доступно только для чтения. Поэтому я не могу, например, сделать user.LoginDetails.Password = hashedandSaltedPassword;

namespace XXXX.Core.Model
{
    public class User
    {
        private LoginDetails loginDetails;

        public virtual LoginDetails LoginDetails
        {
            get { return loginDetails; }
            private set { loginDetails = value; }
        }

        public virtual void AssignLoginDetails(LoginDetails loginDetails)
        {
            this.loginDetails = loginDetails;
        }

        public virtual void HashPassword()
        {
            IHashGenerator hashGenerator = new HashGenerator(new SaltGenerator());
            IHashResult hashResult = hashGenerator.GenerateHash(loginDetails.Password, HashAlgoritm.SHA512);
            loginDetails.Password = String.Concat(hashResult.HashValue, hashResult.Salt);
        }
    }
}

namespace XXXX.Core.Model
{
    public class LoginDetails
    {
        private string username;
        private string password;
        private string confirmPassword;
        private string passwordReminder;
        private bool changePassword;

        // Properties

        #region Constructors

        ...

        public LoginDetails(string username, string password, string confirmPassword, string passwordReminder, bool changePassword)
        {
            this.username = username;
            this.password = password;
            this.confirmPassword = confirmPassword;
            this.passwordReminder = passwordReminder;
            this.changePassword = changePassword;
        }
    }
}

В настоящее время ответственность за хеширование пароля лежит на пользователе (с помощью метода HashPassword), но

1. Является ли это правильной ответственностью за пользователя (в контексте DDD и принципа единой ответственности)

2. Если нет, то где должна находиться эта операция?

3. Если да, то должен ли он вызываться с контроллера, как я делаю?

Спасибо

Ответы [ 2 ]

1 голос
/ 16 января 2010

Не читая ваш код, я бы сказал, что хеширование пароля должно выполняться в модели, чтобы его можно было повторно использовать за пределами MVC-фреймворка. Это имеет тенденцию быть верным во всех средах MVC, которые реализованы на языках, достаточно общих для того, чтобы быть полезными за пределами сети.

0 голосов
/ 16 января 2010

Давайте сделаем шаг назад и посмотрим на более широкую картину: когда мы хотим получить пароль в открытом виде и хэшировать его?

  1. когда пользователь создает или меняем свой пароль, и нам нужно хранить его
  2. когда пользователь входит в систему, и мы нужно сравнить введенное пароль с сохраненным

В настоящее время ваша реализация обращается только к первому экземпляру. Поэтому вам нужен метод, который принимает чистый пароль и возвращает хешированный.

Что касается того, куда должен идти этот метод ...

Принцип единой ответственности не означает, что класс делает буквально одно. Это означает, что класс обрабатывает только те вещи, которые явно находятся в пределах его компетенции.

Итак, рассмотрим связь между пользователем и хешированным паролем. Можете ли вы иметь пользователя без хешированного пароля? Вы когда-нибудь захотите работать с хешированным паролем без его пользователя? У вас есть другие объекты, которые имеют хешированный пароль, кроме пользователя? Если ответом на эти вопросы будет «Нет», то я бы сказал, что метод хеширования паролей явно принадлежит классу User и действительно повышает его согласованность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...