Dot-Net

實現 UserManager 以使用自定義類和儲存過程

  • August 1, 2017

我的應用程序的所有身份驗證和授權過程都是使用儲存過程完成的。我編寫了一個包含我需要的所有功能的類,例如GetUsers, Login, AddRole,AddMember等。管理使用者、角色和權限的管理頁面也是通過使用這個類來完成的。

我只需要添加authentication(我的意思是那個authorize屬性),用於登錄和註銷的 cookie,並為每個登錄儲存一些伺服器端數據。我想我需要為此實施Identity

在那種情況下,你能指導我實施嗎?似乎您需要做的最基本的事情是實現一個create將實例傳遞IUserStore給建構子的方法。但是我不需要任何使用者或角色的表,我該如何實現這個方法?

這是目前類,如果您需要查看我使用儲存過程的自定義身份驗證類,請告訴我。

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;
   }
}

正如alisabzevari建議的那樣,您必須實現IUserStore

您甚至不依賴於定義的儲存和表結構。您可以自定義儲存層的每一位。

我做了一些實驗並嘗試實現自己的UserManagerRoleManager使用不同的儲存,例如Biggy

.NET 的基於文件的文件儲存。

你可以在 GitHub 上找到程式碼

首先要做的是實現您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 實現。您必須實現的主要方法是CreateAsync

public System.Threading.Tasks.Task CreateAsync(User user)
{
   // Saves the user in your storage.
   return Task.FromResult(user);
}

它將收到一個IUser您必須保留在自定義儲存中並返回的資訊。

如果您查看我實現的程式碼,您會發現我使用了一些介面IUserRoleStore,等等,因為我需要使用角色和聲明 IUserPasswordStoreIUserClaimStore

我也實現了我自己的 SignInManager.

一旦你定義了所有的實現,你就可以在啟動時引導一切:

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然後將呼叫另一個方法:

public System.Threading.Tasks.Task<User> FindByIdAsync(int userId)
{
   // Fetch - again - your user from the DB with the Id.
   return Task.FromResult(user);
}

同樣,您必須使用您的儲存過程通過他/她的 id 找到您的使用者。

如果您從 github 下載我的項目並使用它,您會注意到其中大多數方法將被多次呼叫。不要害怕。它就是這樣兒的。

我建議您在UserStore的每個方法中都插入斷點,並查看所有內容如何組合在一起。

引用自:https://stackoverflow.com/questions/30825546