我们的团队决定为我们的项目使用域驱动设计架构。现在正在进行讨论,“我们可以在DDD中使用ASP.NET身份吗?”。
在DDD设计中使用ASP.NET标识是否有任何缺点。
我很困惑,无法做出决定。
我已经搜索过了,但我没有想到。
任何帮助都会很明显。
答案 0 :(得分:21)
这些问题揭示了一些误解:
您似乎将领域模型视为一个整体模型,您可以将每个应用程序放入其中。相反,请专注于战略模式以区分有界上下文。将域视为几个松散互连组件的组合。然后确定您的核心域名是什么,并在那里应用DDD战术模式。并非每个ccomponent都需要DDD。其中一些人甚至不应该使用DDD。特别是 - 通用域名,如身份验证。
DDD与技术无关(某些方面)所以是的,您可以使用ASP.NET Identity或任何您喜欢的库。
身份验证通常属于“应用程序”层,而不属于“域”层。
但是 - 如果在您的域中存在用户/客户/人的概念,则可能需要使用身份组件提供的身份。但是你必须明白,有界上下文中User的含义与Identity in Identity中的含义不同。这些概念不一样。虽然他们都指的是坐在某个地方并点击你应用程序的GUI的同一个身体的人,但他们是他的两个不同的模型(或投影),用于不同的目的。所以你不应该在有界的上下文中重用ASP.NET User类。
相反 - 单独的上下文应该通过反腐败层进行通信。基本上,您必须在有界上下文中创建一些服务(仅限接口),以生成特定于上下文的User对象。在基础结构层中实现的该接口的实现将是ASP.NET标识的包装,它将获得ASP.NET标识用户并生成相应的有界上下文用户。
答案 1 :(得分:1)
你可以使用任何你喜欢的东西。但要注意污染特定的解决方案。如果您的域模型被数百行asp.net技术类型的管道代码搞砸了,这使得您的域逻辑难以察觉并且您缺少DDD点。
在理想情况下 - 您的域模型应仅依赖于编程语言。
此外 - 您可能会在我很久以前的user session related code实施中找到一些有用的东西。
答案 2 :(得分:1)
我是DDD的新手。但我实现了与Identity和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);
}
然后是存储库:
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
}