应用程序的哪一部分应负责散列用户的密码?

时间:2010-01-16 07:17:28

标签: asp.net-mvc passwords

我正在编写一个ASP.NET MVC应用程序,它将提供用户注册功能,但我不确定应用程序的哪个部分(例如User Domain模型对象,Controller,ViewModelMappers)应该负责散列用户的密码。我有一个注册页面,在我的UserController中使用强类型ViewModel和Register操作,如下所示:

[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对象的内部暴露超出绝对要求的密码属性是只读的。所以我不能举例如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 个答案:

答案 0 :(得分:1)

在不阅读代码的情况下,我认为散列密码应该在模型中完成,这样它就可以在MVC框架之外重用。这在所有MVC框架中都是如此,这些框架以通用的语言实现,足以在Web之外使用。

答案 1 :(得分:0)

让我们退后一步,看看更广泛的图景:我们什么时候想要明确地输入密码并将其哈希?

  1. 当用户创建或时 更改密码,我们需要 存储它
  2. 当用户登录时,我们 需要比较输入的 密码与存储的密码
  3. 目前,您的实现仅解决第一个实例。所以你需要一个接受清除密码并返回散列密码的方法。

    至于那种方法应该去哪里......

    单一责任原则并不意味着一个阶级确实是一件事。这意味着该类只处理明显属于其职权范围的事物。

    因此,考虑用户和散列密码之间的关系。你有没有用户没有哈希密码?您是否曾希望在没有用户的情况下使用哈希密码?除了用户之外,您是否还有其他具有哈希密码的对象?如果这些问题的答案是“否”,那么我认为密码哈希方法显然属于用户类,并且确实增加了它的凝聚力。