我们可以在领域驱动设计中使用ASP.NET标识吗?

0g0grzrc  于 2023-10-21  发布在  .NET
关注(0)|答案(4)|浏览(127)

我们的团队决定为我们的项目使用领域驱动设计架构。现在讨论的是,“我们可以在DDD中使用ASP.NET标识?“.
在DDD设计中使用ASP.NET标识有什么缺点吗?
我对这件事很难作出决定。
我找过了,但没找到。
任何帮助都是值得的。

kokeuurv

kokeuurv1#

这些问题揭示了几个误解:
看起来您将域模型看作是将应用程序的每一部分都放在其中的整体模型。相反,要专注于战略模式,以区分有界上下文。将域视为几个松散互连的组件的组合。然后确定您的核心域是什么,并在那里应用DDD战术模式。并不是所有的ccomponent都需要DDD。有些人甚至不应该使用DDD。特别是通用域,如身份验证。
DDD是技术不可知的(在某种程度上),所以是的,你可以使用ASP.NETIdentity或任何你喜欢的库。
身份验证通常属于应用层,而不是域层。
但是,如果在您的域中存在用户/客户端/个人的概念,则可能需要使用身份组件提供的身份。但是你必须明白,在你的有界上下文中User的含义与Identity组件中User的含义是不同的。这不是同一个概念。虽然它们都指的是坐在某个地方并点击应用程序GUI的同一个物理人,但它们是他的两个不同模型(或投影),用于不同的目的。因此,您不应该在有界上下文中重用ASP.NETUser类。
相反,独立的上下文应该通过一个中断层进行通信。基本上,您必须在有界上下文中创建一些服务(仅接口),以生成特定于上下文的User对象。该接口在基础结构层的实现将是一个ASP.NETIdentity的 Package 器,它获取ASP.NETIdentity用户并产生相应的有界上下文用户。

rmbxnbpk

rmbxnbpk2#

我是DDD的新手。但我实现了与身份和DDD的集成。虽然我怀疑它真的坚持DDD的原则。
我从实体开始:

public partial class User : IdentityUser {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager) {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
        /// <summary>
        /// The Date the User Registered for general information purposes
        /// </summary>
        public DateTime DateRegistered { get; set; }
    }

然后接口:

public interface IUserRepository:IBaseRepository<User> {
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns>Identity Result</returns>
        Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe);
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser);
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code);
        void ForgotPassword();
        void ForgotPasswordConfirmation();
        void ResetPassword();
        void ResetPasswordConfirmation();
        void ExternalLogin();
        void SendCode();
        void ExternalLoginCallback();
        void ExternalLoginConfirmation();
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        void Logoff(IAuthenticationManager AuthenticationManager);
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        User GetUser(string Email);
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        User GetUserById(string ID);
    }

然后是Repository:

public class UserRepository : BaseRepository<User>, IUserRepository {
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        public async Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code) =>
            await userManager.ConfirmEmailAsync(userId, code);

        public void ExternalLogin() {
            throw new NotImplementedException();
        }

        public void ExternalLoginCallback() {
            throw new NotImplementedException();
        }

        public void ExternalLoginConfirmation() {
            throw new NotImplementedException();
        }

        public void ForgotPassword() {
            throw new NotImplementedException();
        }

        public void ForgotPasswordConfirmation() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        public User GetUser(string Email) =>
            _context.Users.Where(p => p.Email == Email).FirstOrDefault();
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        public User GetUserById(string ID) => 
            _context.Users.Find(ID);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        public async Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe) =>
            await signinManager.PasswordSignInAsync(email, password, rememberMe, shouldLockout: false);
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        public void Logoff(IAuthenticationManager AuthenticationManager) {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        }
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns>Identity Result</returns>
        public async Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password) =>
            await userManager.CreateAsync(user, password);

        public void ResetPassword() {
            throw new NotImplementedException();
        }

        public void ResetPasswordConfirmation() {
            throw new NotImplementedException();
        }

        public void SendCode() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        public async Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser) =>
            await signinManager.TwoFactorSignInAsync(provider, code, isPersistent: rememberMe, rememberBrowser: rememberBrowser);
    }

IService:

public interface IUserService {
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns></returns>
        Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns></returns>
        Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe);
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns></returns>
        Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser);
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns></returns>
        Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code);
        void ForgotPassword();
        void ForgotPasswordConfirmation();
        void ResetPassword();
        void ResetPasswordConfirmation();
        void ExternalLogin();
        void SendCode();
        void ExternalLoginCallback();
        void ExternalLoginConfirmation();
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        void Logoff(IAuthenticationManager AuthenticationManager);
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        User GetUser(string Email);
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        User GetUserById(string ID);
    }

服务内容:

public class UserService : ServiceBase, IUserService {

        #region Private Field

        private IUserRepository _userRepository;

        #endregion

        #region Constructor
        /// <summary>
        /// Constructor to initialise User Repository
        /// </summary>
        /// <param name="userRepository"></param>
        public UserService(IUserRepository userRepository) {
            _userRepository = userRepository;
        }

        #endregion

        #region Methods
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        public Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code) =>
            _userRepository.ConfirmEmail(userManager, userId, code);

        public void ExternalLogin() {
            throw new NotImplementedException();
        }

        public void ExternalLoginCallback() {
            throw new NotImplementedException();
        }

        public void ExternalLoginConfirmation() {
            throw new NotImplementedException();
        }

        public void ForgotPassword() {
            throw new NotImplementedException();
        }

        public void ForgotPasswordConfirmation() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        public User GetUser(string Email) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        public User GetUserById(string ID) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        public Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe) =>
            _userRepository.Login(signinManager, email, password, rememberMe);
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        public void Logoff(IAuthenticationManager AuthenticationManager) {
            _userRepository.Logoff(AuthenticationManager);
        }
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        public Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password) =>
            _userRepository.Register(userManager, user, password);

        public void ResetPassword() {
            throw new NotImplementedException();
        }

        public void ResetPasswordConfirmation() {
            throw new NotImplementedException();
        }

        public void SendCode() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        public Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser) =>
            _userRepository.VerifyCode(signinManager, provider, code, rememberMe, rememberBrowser);

        #endregion

    }
fcg9iug3

fcg9iug33#

你可以用任何你喜欢的东西。但是要注意特定的解决方案会造成污染。如果您的域模型被数百行asp.net技术类型的管道代码弄得一团糟,使您的域逻辑难以理解,那么您就错过了DDD的要点。
在理想的情况下-您的域模型应该只依赖于编程语言。
另外,你可能会从我很久以前实现的用户会话相关代码中发现一些有用的东西。

vfh0ocws

vfh0ocws4#

您应该定义域层可以使用的公共接口或抽象,而无需了解基础结构层的具体实现细节。在您的解决方案中,创建一个名为“ApplicationCore”或“SharedKernel”的单独项目或文件夹,以定义域层可以依赖的公共接口或抽象,或者只是将这些接口放在域层中。

YourSolution/
├── YourApp/
│   ├── ...
│
├── YourApp.Infrastructure/
│   ├── Data/
│   │   ├── ApplicationDbContext.cs
│   │
│   ├── Identity/
│   │   ├── ApplicationUser.cs
│   │
│   ├── ...
│
├── YourApp.ApplicationCore/      // Create this project or folder
│   ├── Interfaces/
│   │   ├── IApplicationUser.cs    // Define an interface for ApplicationUser
│   │
│   ├── ...
│
├── ...

在域层:

public interface IApplicationUser
{
    string Id { get; }
    string UserName { get; set; }
    // Define other properties and methods needed by the Domain layer.
}

在基础设施层中:

public class ApplicationUser : IdentityUser, IApplicationUser
{
   // Implement the interface members here.
}

相关问题