Asp.net-Mvc-5

ASP.net 身份禁用使用者

  • December 27, 2013

在 MVC 5 中使用新的 ASP.net 身份,我們如何禁用使用者登錄?我不想刪除他們,也許只是在一段時間內禁用他們的帳戶。

有沒有人對此有任何想法,因為我在 ASPNetUsers 表上看不到狀態列或任何內容。

更新:正如 CountZero 指出的那樣,如果您使用的是 v2.1+,那麼您應該先嘗試使用他們添加的鎖定功能,然後再嘗試下面的解決方案。有關完整範例,請參閱他們的部落格文章:http: //blogs.msdn.com/b/webdev/archive/2014/08/05/announcing-rtm-of-asp-net-identity-2-1-0.aspx


2.0 版具有可用於鎖定使用者的 IUserLockoutStore 介面,但缺點是除了 UserManager 類公開的傳遞方法之外,沒有 OOB 功能可以實際利用它。例如,如果它將鎖定計數作為標準使用者名/密碼驗證過程的一部分實際增加,那就太好了。但是,實現自己是相當微不足道的。

步驟#1:創建一個實現 IUserLockoutStore 的自定義使用者儲存。

// I'm specifying the TKey generic param here since we use int's for our DB keys
// you may need to customize this for your environment
public class MyUserStore : IUserLockoutStore<MyUser, int>
{
   // IUserStore implementation here

   public Task<DateTimeOffset> GetLockoutEndDateAsync(MyUser user)
   {
       //..
   }

   public Task SetLockoutEndDateAsync(MyUser user, DateTimeOffset lockoutEnd)
   {
       //..
   }

   public Task<int> IncrementAccessFailedCountAsync(MyUser user)
   {
       //..
   }

   public Task ResetAccessFailedCountAsync(MyUser user)
   {
       //..
   }

   public Task<int> GetAccessFailedCountAsync(MyUser user)
   {
       //..
   }

   public Task<bool> GetLockoutEnabledAsync(MyUser user)
   {
       //..
   }

   public Task SetLockoutEnabledAsync(MyUser user, bool enabled)
   {
       //..
   }
}

第 2 步:在登錄/註銷操作中使用以下類代替 UserManager,將自定義使用者儲存的實例傳遞給它。

public class LockingUserManager<TUser, TKey> : UserManager<TUser, TKey>
   where TUser : class, IUser<TKey> 
   where TKey : IEquatable<TKey> 
{
   private readonly IUserLockoutStore<TUser, TKey> _userLockoutStore;

   public LockingUserManager(IUserLockoutStore<TUser, TKey> store)
       : base(store)
   {
       if (store == null) throw new ArgumentNullException("store");

       _userLockoutStore = store;
   }

   public override async Task<TUser> FindAsync(string userName, string password)
   {
       var user = await FindByNameAsync(userName);

       if (user == null) return null;

       var isUserLockedOut = await GetLockoutEnabled(user);

       if (isUserLockedOut) return user;

       var isPasswordValid = await CheckPasswordAsync(user, password);

       if (isPasswordValid)
       {
           await _userLockoutStore.ResetAccessFailedCountAsync(user);
       }
       else
       {
           await IncrementAccessFailedCount(user);

           user = null;
       }

       return user;
   }

   private async Task<bool> GetLockoutEnabled(TUser user)
   {
       var isLockoutEnabled = await _userLockoutStore.GetLockoutEnabledAsync(user);

       if (isLockoutEnabled == false) return false;

       var shouldRemoveLockout = DateTime.Now >= await _userLockoutStore.GetLockoutEndDateAsync(user);

       if (shouldRemoveLockout)
       {
           await _userLockoutStore.ResetAccessFailedCountAsync(user);

           await _userLockoutStore.SetLockoutEnabledAsync(user, false);

           return false;
       }

       return true;
   }

   private async Task IncrementAccessFailedCount(TUser user)
   {
       var accessFailedCount = await _userLockoutStore.IncrementAccessFailedCountAsync(user);

       var shouldLockoutUser = accessFailedCount > MaxFailedAccessAttemptsBeforeLockout;

       if (shouldLockoutUser)
       {
           await _userLockoutStore.SetLockoutEnabledAsync(user, true);

           var lockoutEndDate = new DateTimeOffset(DateTime.Now + DefaultAccountLockoutTimeSpan);

           await _userLockoutStore.SetLockoutEndDateAsync(user, lockoutEndDate);
       }
   }
}

範例

   [AllowAnonymous]
   [HttpPost]
   public async Task<ActionResult> Login(string userName, string password)
   {
       var userManager = new LockingUserManager<MyUser, int>(new MyUserStore())
       {
           DefaultAccountLockoutTimeSpan = /* get from appSettings */,
           MaxFailedAccessAttemptsBeforeLockout = /* get from appSettings */
       };

       var user = await userManager.FindAsync(userName, password);

       if (user == null)
       {
           // bad username or password; take appropriate action
       }

       if (await _userManager.GetLockoutEnabledAsync(user.Id))
       {
           // user is locked out; take appropriate action
       }

       // username and password are good
       // mark user as authenticated and redirect to post-login landing page
   }

如果您想手動鎖定某人,您可以設置您要簽入的任何標誌MyUserStore.GetLockoutEnabledAsync()

await userManager.SetLockoutEnabledAsync(applicationUser.Id, true);
await userManager.SetLockoutEndDateAsync(DateTime.Today.AddYears(10));

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