是的,非常好的问题.就像"安德鲁·库珀"一样,我们的团队也经历了这一切.
我们采用了以下方法(对或错):
Custom Membership Provider个
我和其他开发者都不是内置ASP的粉丝.网络会员Provider .对于我们的网站(简单的、由UGC驱动的社交网站)来说,它太臃肿了.我们创建了一个非常简单的应用程序,可以满足我们的应用程序的需要,仅此而已.而内置的会员服务Provider 可以满足您的所有需求,但很可能不会.
Custom Forms Authentication Ticket/Authentication
我们应用程序中的一切都使用接口驱动的依赖项注入(StructureMap).这包括表单身份验证.我们创建了一个非常薄的界面:
public interface IAuthenticationService
{
void SignIn(User user, HttpResponseBase httpResponseBase);
void SignOut();
}
这个简单的界面允许简单的模拟/测试.通过实现,我们创建了一个自定义表单身份验证票证,其中包含:每个HTTP请求都需要用户ID和角色之类的内容,它们不会经常更改,因此不应该在每个请求中提取.
然后,我们使用一个操作过滤器来解密表单身份验证票证(包括角色),并将其粘贴到HttpContext.Current.User.Identity
中(我们的主要对象也是基于接口的).
Use of [Authorize] and [AdminOnly]
我们仍然可以使用MVC中的授权属性.我们还 for each 角色创建了一个.[AdminOnly]
只判断当前用户的角色,并抛出401(禁止).
Simple, single table for User, simple POCO个
所有用户信息都存储在一个表中(除了"可选"用户信息,例如个人资料兴趣).这被映射到一个简单的POCO(实体框架),它也在对象中内置了域逻辑.
User Repository/Service
简单的用户存储库是domain-specific.例如更改密码、更新配置文件、检索用户等.存储库调用我上面提到的用户对象上的域逻辑.该服务是存储库顶部的一个薄包装,它将单个存储库方法(例如Find)分离为更专门的方法(FindById、FindByNickname).
Domain seperated from security
我们的"域",即用户及其关联信息.这包括姓名、个人资料、Facebook/社交整合等.
像"登录"、"注销"这样的内容涉及authentication个,而像"User.IsInRole"这样的内容涉及authorization个,因此不属于该域.
因此,我们的控制器与IAuthenticationService
和IUserService
同时工作.
创建概要文件是域逻辑的一个完美例子,它也与身份验证逻辑混合在一起.
下面是我们的
[HttpPost]
[ActionName("Signup")]
public ActionResult Signup(SignupViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Map to Domain Model.
var user = Mapper.Map<SignupViewModel, Core.Entities.Users.User>(model);
// Create salt and hash password.
user.Password = _authenticationService.SaltAndHashPassword();
// Signup User.
_userService.Save(user);
// Save Changes.
_unitOfWork.Commit();
// Forms Authenticate this user.
_authenticationService.SignIn(user, Response);
// Redirect to homepage.
return RedirectToAction("Index", "Home", new { area = "" });
}
catch (Exception exception)
{
ModelState.AddModelError("SignupError", "Sorry, an error occured during Signup. Please try again later.");
_loggingService.Error(exception);
}
}
return View(model);
}
Summary个
以上这些对我们很有效.我有一个简单的用户表,而不是ASP.网络会员Provider .它很简单,代表我们的domain,而不是ASP.NET对它的表示.
That being said个,就像我说的,我们有一个简单的网站.如果你在一家银行网站上工作,那么我在重新发明轮子时会很小心.
我的建议是在考虑身份验证之前,先创建域/模型.(当然,这就是DDD的全部内容).
Then制定出你的安全要求,并 Select 适当的身份验证Provider (现成的或定制的).
不要让ASP.NET指定域的设计方式.这是大多数人都会落入的trap (包括我,在以前的项目中).
祝好运!