如何整合"用户"在我与认证用户DDD模式? [英] How do integrate "Users" in my DDD model with authenticating users?

查看:136
本文介绍了如何整合"用户"在我与认证用户DDD模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要创建我的第一个ASP.NET MVC的网站,并一直在努力遵循领域驱动发展。我的网站是一个项目协作网站,用户可以分配给一个或多个项目在网站上。任务然后加入项目,并在一个项目中的用户可以被分配到任务。因此,一个用户是我的域模型的基本概念。

我的计划是有一个包含所有关于用户的信息,并可以通过IUserRepository访问的用户模型对象。每个用户可以通过用户ID来识别。虽然我不知道在这一点上,如果我想的用户ID是一个字符串或整数。

应该怎样我的域对象的用户和IUserRepository涉及到我的网站更多的管理功能,如授权用户,并允许他们登录?我将如何整合与ASP.NET的其他方面,如HttpContext.User中,HttpContext.Profile,一个自定义的MembershipProvider,定制ProfileProvider,或自定义AuthorizeAttribute我的域模型?

我应该创建一个自定义的MembershipProvider和或ProfileProvider它包装我IUserRepository?虽然,我也可以预见,为什么我可能要在用户的信息在我的域模型从我的网站用户的授权分开。例如,在将来,我可能想从窗体身份验证切换到Windows身份验证。

它会更好不要试图另起炉灶,并内置到ASP.NET标准SqlMembershipProvider的坚守?每个用户的个人信息将被存储在域模式(用户/ IUserRepository),但这并不包括他们的密码。然后我会使用标准的ASP.NET成员资格的东西来处理创建和授权用户?所以就需要一些code的地方,就知道在当他们的帐户创建IUserRepository或者他们首次登录新用户创建一个配置文件。


解决方案

是 - 非常好的问题。像@Andrew库珀,我们的团队还通过这一切了。

我们就跟着以下的方法(正确或错误):


  

自定义成员资格提供


无论是我还是其他开发商都建在ASP.NET成员资格提供的粉丝。这是什么我们的网站是关于(简单,教资会推动社会网站)的方式过于臃肿。我们创建了一个非常简单的,做我们的应用程序所需要的,仅此而已。而内置的成员资格提供程序做了你的的一切可能的需要,但最有可能不会。


  

自定义窗体身份验证票/验证


在我们的应用程序的一切使用界面驱动的依赖注入(StructureMap)。这包括窗体身份验证。我们创建了一个非常薄的接口:

 公共接口IAuthenticationService
{
   签到无效(用户用户的Htt presponseBase HTT presponseBase);
   无效SignOut();
}

这个简单的接口可方便地嘲弄/测试。与实施,我们创建一个包含自定义窗体身份验证票证:东西,如用户ID和角色,这是需要在每个HTTP请求,不要频繁改变,因此不应该在每次请求获取。

我们再使用一个动作过滤器来解密窗体身份验证票(包括角色),并把它贴在 HttpContext.Current.User.Identity (对此我们的主要对象也接口为基础的)。


  

使用的[授权]和[AdminOnly]


我们仍然可以利用授权的MVC属性。而且我们还创建了一个为每个角色。 [AdminOnly] 简单地检查当前用户的角色,并抛出一个401(禁止)。


  

有关用户的简单,单表,简单的POCO


所有的用户信息被存储在一个单一的表(以可选的用户信息,如信息利益除外)。这被映射到一个简单的POCO(实体框架),其中也有内置的对象域的逻辑


  

用户存储库/服务


简单的用户存储库是的特定领域。例如,更改密码,更新个人资料,检索用户等资源库的东西调用到我上面提到的用户对象上的域逻辑。该服务是对存储库,它的方式隔开单一存储库的方法之上的瘦包装(如查找),为更多的那些(FindById,FindByNickname)。


  

域从安全性分开


我们的域用户和他/她的关联信息。这包括名称,简介,脸谱/社会融合等。

像登陆的东西,注销正在处理的验证的之类的东西User.IsInRole用的授权的,因此不要在域属于交易。

所以我们的控制器一起工作既 IAuthenticationService IUserService

创建一个配置文件是域逻​​辑的一个很好的例子,那就是身份验证逻辑也混。

下面就是我们的样子:

  [HttpPost]
[ActionName(注册)]
公众的ActionResult注册(SignupViewModel模型)
{
    如果(ModelState.IsValid)
    {
        尝试
        {
            //映射到域模型。
            VAR用户= Mapper.Map< SignupViewModel,Core.Entities.Users.User>(模型);            //创建盐和哈希密码。
            user.password的= _authenticationService.SaltAndHashPassword();            //注册用户。
            _userService.Save(用户);            // 保存更改。
            _unitOfWork.Commit();            //表单验证该用户。
            _authenticationService.SignIn(用户,响应);            //重定向到主页。
            返回RedirectToAction(指数,家,新{面积=});
        }
        赶上(例外的例外)
        {
            ModelState.AddModelError(SignupError,对不起,注册过程中出错请稍后再试一次。);
            _loggingService.Error(例外);
        }
    }    返回查看(模型);
}


  

摘要


以上为我们运作良好。我的的有一个简单的用户表,并不算臃肿的疯狂是ASP.NET成员提供商。它的简单和再presents我们的的,不是ASP.NET的再$它p $ psentation。

话虽这么说,正如我所说的,我们有一个简单的网站。如果你在一个银行网站工作的话,我会小心重新发明轮子。

我要使用的建议是先创建域/型号,之前你也别想认证。 (当然,这是DDD是关于什么的)。

然后的工作你的安全要求,并选择一个身份验证提供者(下架,或自定义)适当。

不要让ASP.NET决定如何您的域名应设计。这是陷阱大多数人陷入(包括我,在previous项目)。

祝你好运!

I'm creating my first ASP.NET MVC site and have been trying to follow domain driven development. My site is a project collaboration site where users can be assigned to one or more projects on the site. Tasks are then added to projects, and users with in a project can be assigned to tasks. So a "User" is a fundamental concept of my domain model.

My plan is to have a "User" model object which contains all the information about a user and can be accessed through an IUserRepository. Each user can be identified by a UserId. Although I'm not sure at this point if I want the UserId to be a string or integer.

How should my domain objects User and IUserRepository relate to the more administrative functions of my site like authorizing users and allowing them to login? How would I integrate my domain model with other aspects of ASP.NET such as HttpContext.User, HttpContext.Profile, a custom MemberShipProvider, a custom ProfileProvider, or custom AuthorizeAttribute?

Should I create a custom MembershipProvider and or ProfileProvider which wraps my IUserRepository? Although, I can also foresee why I may want to separate the User information in my domain model from the authorization of a user on my site. For example in the future I may want to switch to windows authentication from forms authentication.

Would it be better to not try and reinvent the wheel and stick with the standard SqlMembershipProvider built into ASP.NET? Each user's profile information would be stored in the domain model (User/IUserRepository), but this would not include their password. I would then use the standard ASP.NET membership stuff to handle creating and authorizing users? So there would need to be some code somewhere that would know to create a profile for a new users in the IUserRepository when their account is created or the first time they login.

解决方案

Yes - very good question. Like @Andrew Cooper, our team also went through all this.

We went with the following approaches (right or wrong):

Custom Membership Provider

Neither I or the other developer are fans of the built in ASP.NET Membership provider. It's way too bloated for what our site is about (simple, UGC-driven social website). We created a very simple one that does what our application needs, and nothing more. Whereas the built-in membership provider does everything you might need, but most likely won't.

Custom Forms Authentication Ticket/Authentication

Everything in our application uses interface-driven dependency injection (StructureMap). This includes Forms Authentication. We created a very thin interface:

public interface IAuthenticationService
{
   void SignIn(User user, HttpResponseBase httpResponseBase);
   void SignOut();
}

This simple interface allows easy mocking/testing. With the implementation, we create a custom forms authentication ticket containing: things like the UserId and the Roles, which are required on every HTTP request, do not frequently change and therefore should not be fetched on every request.

We then use an action filter to decrypt the forms authentication ticket (including the roles) and stick it in the HttpContext.Current.User.Identity (for which our Principal object is also interface-based).

Use of [Authorize] and [AdminOnly]

We can still make use of the authorization attributes in MVC. And we also created one for each role. [AdminOnly] simply checks the role for the current user, and throws a 401 (forbidden).

Simple, single table for User, simple POCO

All user information is stored in a single table (with the exception of "optional" user info, such as profile interests). This is mapped to a simple POCO (Entity Framework), which also has domain-logic built into the object.

User Repository/Service

Simple User Repository that is domain-specific. Things like changing password, updating profile, retrieving users, etc. The repository calls into domain logic on the User object i mentioned above. The service is a thin wrapper on top of the repository, which seperates single repository methods (e.g Find) into more specialized ones (FindById, FindByNickname).

Domain seperated from security

Our "domain" the User and his/her's association information. This includes name, profile, facebook/social integration, etc.

Things like "Login", "Logout" are dealing with authentication and things like "User.IsInRole" deals with authorization and therefore do not belong in the domain.

So our controllers work with both the IAuthenticationService and the IUserService.

Creating a profile is a perfect example of domain logic, that is mixed with authentication logic also.

Here's what our's looks like:

[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

The above has worked well for us. I love having a simple User table, and not that bloated madness that is the ASP.NET Membership provider. It's simple and represents our domain, not ASP.NET's representation of it.

That being said, as i said we have a simple website. If you're working on a banking website then i would be careful about re-inventing the wheel.

My advice to use is create your domain/model first, before you even think about authentication. (of course, this is what DDD is all about).

Then work out your security requirements and choose an authentication provider (off the shelf, or custom) appropriately.

Do not let ASP.NET dictate how your domain should be designed. This is the trap most people fall into (including me, on a previous project).

Good luck!

这篇关于如何整合&QUOT;用户&QUOT;在我与认证用户DDD模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆