我正在编写一个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。如果是这样,它应该像我一样从控制器调用吗?
由于
答案 0 :(得分:1)
在不阅读代码的情况下,我认为散列密码应该在模型中完成,这样它就可以在MVC框架之外重用。这在所有MVC框架中都是如此,这些框架以通用的语言实现,足以在Web之外使用。
答案 1 :(得分:0)
让我们退后一步,看看更广泛的图景:我们什么时候想要明确地输入密码并将其哈希?
目前,您的实现仅解决第一个实例。所以你需要一个接受清除密码并返回散列密码的方法。
至于那种方法应该去哪里......
单一责任原则并不意味着一个阶级确实是一件事。这意味着该类只处理明显属于其职权范围的事物。
因此,考虑用户和散列密码之间的关系。你有没有用户没有哈希密码?您是否曾希望在没有用户的情况下使用哈希密码?除了用户之外,您是否还有其他具有哈希密码的对象?如果这些问题的答案是“否”,那么我认为密码哈希方法显然属于用户类,并且确实增加了它的凝聚力。