实施 UserManager 以使用自定义 class 和存储过程
Implementing UserManager to use a custom class and Stored Procedures
我的应用程序的所有身份验证和授权过程都是使用存储过程完成的。我已经写了一个 class 具有我需要的所有功能,例如GetUsers
、Login
、AddRole
、AddMember
等。
此外,用于管理用户、角色和权限的管理页面也是使用此 class.
完成的
我只需要添加 authentication
(我的意思是 authorize
属性)、用于登录和注销的 cookie 以及为每次登录存储一些服务器端数据。我想我需要为此实施 Identity
?
在那种情况下,你能指导我实现它吗?看来您需要做的最基本的事情是实现一个 create
方法,该方法将 IUserStore
的实例传递给构造函数。但是我不需要任何用户或角色表,我该如何实现这个方法?
这是当前的 class,如果您需要查看我使用存储过程的自定义身份验证 class,请告诉我。
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store) : base(store) { }
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
//AppUserManager manager = new AppUserManager();
//return manager;
return null;
}
}
您必须实现 IUserStore 接口。请参阅 this article 以了解如何为 ASP.NET 身份实施自定义存储提供程序。
如alisabzevari suggested you have to implement your IUserStore.
您甚至不依赖定义的存储和 table 结构。
您可以自定义存储层的每一位。
我做了一些实验并尝试使用不同的存储实现我自己的 UserManager
和 RoleManager
,例如 Biggy:
A File-based Document Store for .NET.
您可以在 GitHub 上找到代码 here。
首先要做的是实施您的 UserManager
,您可以在其中配置密码验证要求:
public class AppUserManager : UserManager<AppUser, int>
{
public AppUserManager (IUserStore<AppUser, int> store): base(store)
{
this.UserLockoutEnabledByDefault = false;
// this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);
// this.MaxFailedAccessAttemptsBeforeLockout = 10;
this.UserValidator = new UserValidator<User, int>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
// Configure validation logic for passwords
this.PasswordValidator = new PasswordValidator
{
RequiredLength = 4,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
}
}
然后定义你的IUserStore
implementation。您必须实现的主要方法是 CreateAsync
:
public System.Threading.Tasks.Task CreateAsync(User user)
{
// Saves the user in your storage.
return Task.FromResult(user);
}
它将收到一个 IUser
,您必须将其保存在您的自定义存储中并 return 它。
如果你看一下我 implemented 的代码,你会发现我使用了一些接口 IUserRoleStore
、IUserPasswordStore
、IUserClaimStore
等等因为我需要使用角色和声明。
我也实现了我的 own SignInManager
。
一旦您定义了所有实现,您就可以 bootstrap startup:
中的所有内容
app.CreatePerOwinContext<Custom.Identity.UserManager>(() => new Custom.Identity.UserManager(new Custom.Identity.UserStore(folderStorage)));
app.CreatePerOwinContext<Custom.Identity.RoleManager>(() => new Custom.Identity.RoleManager(new Custom.Identity.RoleStore(folderStorage)));
app.CreatePerOwinContext<Custom.Identity.SignInService>((options, context) => new Custom.Identity.SignInService(context.GetUserManager<Custom.Identity.UserManager>(), context.Authentication));
您可以查看我的 AccountController 我尝试验证用户的地方:
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
调用 PasswordSignInAsync
后,您会注意到 UserManager
的一些方法将被调用。第一个将是 FindByNameAsync:
public System.Threading.Tasks.Task<User> FindByNameAsync(string userName)
{
//Fetch your user using the username.
return Task.FromResult(user);
}
我想您必须实施存储过程,从数据库中获取用户。
然后另一种方法 FindByIdAsync
将是 called:
public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
// Fetch - again - your user from the DB with the Id.
return Task.FromResult(user);
}
同样,您必须使用存储过程通过 his/her id 查找您的用户。
如果您从 github 下载我的项目并试用它,您会发现其中的大部分方法都会被多次调用。不要害怕。它就是这样儿的。
我建议您在 UserStore 的每个方法中都插入断点,然后看看它们是如何组合在一起的。
您还可以覆盖 UserManager
class(例如 ApplicationUserManager
)中的方法来管理授权。这是一个使用自定义 UserManager.FindAsync
逻辑的示例。 UserManager
class 在身份验证期间由 ApplicationOAuthProvider
class 使用。
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager() : base(new EmptyUserStore()) { }
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
return new ApplicationUserManager();
}
public override Task<ApplicationUser> FindAsync(string userName, string password)
{
// Authentication logic here.
throw new NotImplementedException("Authenticate userName and password");
var result = new ApplicationUser { UserName = userName };
return Task.FromResult(result);
}
}
/// <summary>
/// User Store with no implementation. Required for UserManager.
/// </summary>
internal class EmptyUserStore : IUserStore<ApplicationUser>
{
public Task CreateAsync(ApplicationUser user)
{
throw new NotImplementedException();
}
public Task DeleteAsync(ApplicationUser user)
{
throw new NotImplementedException();
}
public Task<ApplicationUser> FindByIdAsync(string userId)
{
throw new NotImplementedException();
}
public Task<ApplicationUser> FindByNameAsync(string userName)
{
throw new NotImplementedException();
}
public Task UpdateAsync(ApplicationUser user)
{
throw new NotImplementedException();
}
public void Dispose()
{
// throw new NotImplementedException();
}
}
请注意,此实现没有利用 IUserStore
接口的优势。
我的应用程序的所有身份验证和授权过程都是使用存储过程完成的。我已经写了一个 class 具有我需要的所有功能,例如GetUsers
、Login
、AddRole
、AddMember
等。
此外,用于管理用户、角色和权限的管理页面也是使用此 class.
我只需要添加 authentication
(我的意思是 authorize
属性)、用于登录和注销的 cookie 以及为每次登录存储一些服务器端数据。我想我需要为此实施 Identity
?
在那种情况下,你能指导我实现它吗?看来您需要做的最基本的事情是实现一个 create
方法,该方法将 IUserStore
的实例传递给构造函数。但是我不需要任何用户或角色表,我该如何实现这个方法?
这是当前的 class,如果您需要查看我使用存储过程的自定义身份验证 class,请告诉我。
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store) : base(store) { }
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
//AppUserManager manager = new AppUserManager();
//return manager;
return null;
}
}
您必须实现 IUserStore 接口。请参阅 this article 以了解如何为 ASP.NET 身份实施自定义存储提供程序。
如alisabzevari suggested you have to implement your IUserStore.
您甚至不依赖定义的存储和 table 结构。
您可以自定义存储层的每一位。
我做了一些实验并尝试使用不同的存储实现我自己的 UserManager
和 RoleManager
,例如 Biggy:
A File-based Document Store for .NET.
您可以在 GitHub 上找到代码 here。
首先要做的是实施您的 UserManager
,您可以在其中配置密码验证要求:
public class AppUserManager : UserManager<AppUser, int>
{
public AppUserManager (IUserStore<AppUser, int> store): base(store)
{
this.UserLockoutEnabledByDefault = false;
// this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(10);
// this.MaxFailedAccessAttemptsBeforeLockout = 10;
this.UserValidator = new UserValidator<User, int>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = false
};
// Configure validation logic for passwords
this.PasswordValidator = new PasswordValidator
{
RequiredLength = 4,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
}
}
然后定义你的IUserStore
implementation。您必须实现的主要方法是 CreateAsync
:
public System.Threading.Tasks.Task CreateAsync(User user)
{
// Saves the user in your storage.
return Task.FromResult(user);
}
它将收到一个 IUser
,您必须将其保存在您的自定义存储中并 return 它。
如果你看一下我 implemented 的代码,你会发现我使用了一些接口 IUserRoleStore
、IUserPasswordStore
、IUserClaimStore
等等因为我需要使用角色和声明。
我也实现了我的 own SignInManager
。
一旦您定义了所有实现,您就可以 bootstrap startup:
中的所有内容app.CreatePerOwinContext<Custom.Identity.UserManager>(() => new Custom.Identity.UserManager(new Custom.Identity.UserStore(folderStorage)));
app.CreatePerOwinContext<Custom.Identity.RoleManager>(() => new Custom.Identity.RoleManager(new Custom.Identity.RoleStore(folderStorage)));
app.CreatePerOwinContext<Custom.Identity.SignInService>((options, context) => new Custom.Identity.SignInService(context.GetUserManager<Custom.Identity.UserManager>(), context.Authentication));
您可以查看我的 AccountController 我尝试验证用户的地方:
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
调用 PasswordSignInAsync
后,您会注意到 UserManager
的一些方法将被调用。第一个将是 FindByNameAsync:
public System.Threading.Tasks.Task<User> FindByNameAsync(string userName)
{
//Fetch your user using the username.
return Task.FromResult(user);
}
我想您必须实施存储过程,从数据库中获取用户。
然后另一种方法 FindByIdAsync
将是 called:
public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
// Fetch - again - your user from the DB with the Id.
return Task.FromResult(user);
}
同样,您必须使用存储过程通过 his/her id 查找您的用户。
如果您从 github 下载我的项目并试用它,您会发现其中的大部分方法都会被多次调用。不要害怕。它就是这样儿的。
我建议您在 UserStore 的每个方法中都插入断点,然后看看它们是如何组合在一起的。
您还可以覆盖 UserManager
class(例如 ApplicationUserManager
)中的方法来管理授权。这是一个使用自定义 UserManager.FindAsync
逻辑的示例。 UserManager
class 在身份验证期间由 ApplicationOAuthProvider
class 使用。
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager() : base(new EmptyUserStore()) { }
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
return new ApplicationUserManager();
}
public override Task<ApplicationUser> FindAsync(string userName, string password)
{
// Authentication logic here.
throw new NotImplementedException("Authenticate userName and password");
var result = new ApplicationUser { UserName = userName };
return Task.FromResult(result);
}
}
/// <summary>
/// User Store with no implementation. Required for UserManager.
/// </summary>
internal class EmptyUserStore : IUserStore<ApplicationUser>
{
public Task CreateAsync(ApplicationUser user)
{
throw new NotImplementedException();
}
public Task DeleteAsync(ApplicationUser user)
{
throw new NotImplementedException();
}
public Task<ApplicationUser> FindByIdAsync(string userId)
{
throw new NotImplementedException();
}
public Task<ApplicationUser> FindByNameAsync(string userName)
{
throw new NotImplementedException();
}
public Task UpdateAsync(ApplicationUser user)
{
throw new NotImplementedException();
}
public void Dispose()
{
// throw new NotImplementedException();
}
}
请注意,此实现没有利用 IUserStore
接口的优势。