【问题标题】:DDD Authentication ServiceDDD 认证服务
【发布时间】:2011-07-11 18:51:36
【问题描述】:

我正在关注 Scott Millet 在专业 ASP.NET 设计模式中的案例研究。在案例研究中,身份验证在基础设施项目中处理。它包含 AspFormsAuthentication : IFormsAuthentication、AspMembershipAuthentication : ILocalAuthenticationService 等实现。

这很好用,因为他使用的是内置的会员提供程序,但是,我不是,所以我需要访问我的存储库。在我的场景中,将我的 ILocalAuthenticationService 和 AspMembershipAuthentication 实现放在 Services 项目中不是更好吗?

我在别处问过,有人回答:

我仍然会将提取凭据的功能放在基础设施层中,因为该层与其他水平层垂直对齐,并且所有层都可以访问它。由于您没有使用 ASP.NET 成员资格提供程序,并且可能正在使用可能仅使用加密凭据的自定义内容,因此您仍然可以使用基础结构层来包装对这些凭据的访问,并允许存储库在需要时使用它们。您可以让服务层获取它们并将它们传递下去,但是您有太多的层来了解数据将如何被检索/持久化以及需要什么授权访问,这在尝试分层和分离关注点时是不好的。

太好了。这是有道理的。但我不知道从这里去哪里。案例研究中的代码:

public class AspMembershipAuthentication : ILocalAuthenticationService 
{
    public User Login(string email, string password)
    {
        User user = new User();
        user.IsAuthenticated= false;

        if (Membership.ValidateUser(email, password))
        {
            MembershipUser validatedUser = Membership.GetUser(email);
            user.AuthenticationToken = validatedUser.ProviderUserKey.ToString();
            user.Email = email;
            user.IsAuthenticated = true;
        }

        return user;
    }

    public User RegisterUser(string email, string password)
    {            
        MembershipCreateStatus status;
        User user = new User();
        user.IsAuthenticated = false;

        Membership.CreateUser(email, password, email, 
                              Guid.NewGuid().ToString(), Guid.NewGuid().ToString(),
                              true, out status);

        if (status == MembershipCreateStatus.Success)
        {
            MembershipUser newlyCreatedUser = Membership.GetUser(email);
            user.AuthenticationToken = newlyCreatedUser.ProviderUserKey.ToString();
            user.Email = email;
            user.IsAuthenticated = true;
        }
        else
        {
            switch (status)
            {
                case MembershipCreateStatus.DuplicateEmail:
                    throw new InvalidOperationException(
                           "There is already a user with this email address.");
                case MembershipCreateStatus.DuplicateUserName:
                    throw new InvalidOperationException(
                           "There is already a user with this email address.");
                case MembershipCreateStatus.InvalidEmail:
                    throw new InvalidOperationException(
                           "Your email address is invalid");
                default:
                    throw new InvalidOperationException(
                    "There was a problem creating your account. Please try again.");
            }
        }

        return user;
    }       
}

如果我不使用会员提供程序,我如何连接到数据库以检查用户名和密码是否匹配,以及其他可能的检查?

【问题讨论】:

  • 身份验证是应用程序级别的问题。它不属于您的域。

标签: c# asp.net-mvc domain-driven-design


【解决方案1】:

在您的基础设施层中创建一个实现 ILocalAuthenticationService 并进行所需调用的类。

或者,如果 ILocalAuthenticationService 过于 ASP.NET-y(具有其用户返回类型),您可能必须推出自己的 ILocalAuthenticationService 变体并实现它。

然后在需要时使用您的 IoC 容器来解析 ILocalAuthenticationService。

【讨论】:

  • 感谢您的回复。我的基础设施层已经有了 ILocalAuthenticationService,并且与上面类似,实现了 AspMembershipAuthentication。我在上面发布的实现使用了默认的 Membership Provider,而我不打算使用它。那么,在基础设施层中,我将如何访问数据以执行上述实现对成员资格提供程序所做的检查?
  • 我明白了——所以你的基础设施层看不到数据层?如果您的身份验证服务位于可以看到数据库的地方——从 IoC 的角度来看,您的客户并不真正关心它来自哪里。如果基础设施层看不到数据库并且您的授权是基于数据库的,那么它就不能存在于基础设施层中,正如您已经发现的那样:)
  • 没错!最初,我计划在服务层中执行此操作。但是,我对此提出质疑,因为“在案例研究中不是这样做的”。所以我问了,但由于关注点分离(来自我发布的报价),建议将其保留在基础设施层中。我正在考虑将它放在服务层中,以便我可以使用我的存储库来与数据库进行通信。基于此,您会提出什么建议?
  • 如果您基于数据库进行身份验证并且基础设施层无权访问数据库,我认为您将身份验证放在服务层中。我完全看不出有什么问题。我知道很难将教条与实践区分开来。无论如何,你的 IoC 会让它变得无关紧要。去吧! :)
  • 哈哈,无论如何,这对我来说是有意义的。感谢您的回复。我在其他地方有另一个线程。如果还有其他问题,我也会在这里发布。
猜你喜欢
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-11
  • 2018-08-12
相关资源
最近更新 更多