As alisabzevari, you suggested implementing IUserStore . <sh> You do not even depend on the structure of the storage and the table. You can customize every bit of your storage level.
I did some experimentation and tried to implement my own UserManager and RoleManager using another repository like Biggy
File-based document repository for .NET.
Here you can find the code here on GitHub.
The first thing to do is to implement the UserManager , where you can configure the requirements for password verification:
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, }; } }
and then define the implementation of IUserStore . The main method you should implement is CreateAsync :
public System.Threading.Tasks.Task CreateAsync(User user) {
he will receive the IUser , which you must save in your specialized repository and return it.
If you look at the code that I used , you can see that I used several interfaces IUserRoleStore , IUserPasswordStore , IUserClaimStore , etc. etc., since I needed to use roles and claims.
I also implemented my own SignInManager .
Once you have defined your entire implementation, you can load everything into 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));
You can check the AccountController where I try to check the user:
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); }
After calling PasswordSignInAsync you will notice that some of the methods of your UserManager will be called. The first will be FindByNameAsync :
public System.Threading.Tasks.Task<User> FindByNameAsync(string userName) {
You will need to implement your stored procedure, I think, where will you select your user from the database.
Then another FindByIdAsync method will be called :
public System.Threading.Tasks.Task<User> FindByIdAsync(int userId) {
Again, you will have to use the stored procedure to find your user by his / her identifier.
If you download my project from github and play with it, you will notice that most of these methods will be called multiple times. Do not be afraid. The way it is.
I would suggest that you insert breakpoints in each UserStore method and see how everything fits together.