2015-10-05 120 views
6

我試圖找到一種方法來禁用Identity 2.0中的用戶,並且似乎無法在其上找到任何信息。如何在Identity 2.0中禁用用戶?

我想基本上將用戶設置爲IsActive = false,並希望在用戶創建後立即執行此操作。但是,我需要一種方法來爲我們的網站管理員設置IsActive。我已經擁有ASP.Net會員資格,但我希望將網站轉換爲MVC和Identity。

對於我的要求,我們要求人們繼續並註冊一個帳戶,但我們希望默認情況下禁用它。然後,當我們收到加盟費時,我們會回去並啓用它們。我們也使用它來禁用用戶,當他們的訂閱已經結束並且他們沒有續約時。

有沒有辦法在不刪除帳戶的情況下禁用帳戶,或者只鎖定X個時間段?到目前爲止,我還沒有找到任何在Identity中禁用用戶的方法,我很驚訝這個問題以前沒有提出過。

回答

11

當您創建安裝了標識位的網站,您的網站將有一個名爲 「IdentityModels.cs」 文件。在這個文件中是一個名爲ApplicationUser的類,它繼承自IdentityUser。

// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. 
public class ApplicationUser : IdentityUser 

書中有評論一個很好的鏈接,便於點擊here

本教程告訴你到底你需要做的,爲您的用戶添加自定義屬性是什麼。

而實際上,甚至不打擾看教程。

1)屬性添加到ApplicationUser類,如:

public bool? IsEnabled { get; set; } 

2)在你的數據庫的AspNetUsers表上同一名稱添加一列。

3)繁榮,就是這樣!

現在在你的AccountController,你有一個註冊的動作如下:

public async Task<ActionResult> Register(RegisterViewModel model) 
     { 
      if (ModelState.IsValid) 
      { 
       var user = new ApplicationUser { UserName = model.Email, Email = model.Email, IsEnabled = true }; 
       var result = await UserManager.CreateAsync(user, model.Password); 
       if (result.Succeeded) 

我已經添加了的IsEnabled =上創建ApplicationUser對象的真實。該值現在將保留在AspNetUsers表的新列中。

然後,您需要通過重寫ApplicationSignInManager中的PasswordSignInAsync來處理檢查此值作爲登錄過程的一部分。

我做到了,如下所示:

public override Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool rememberMe, bool shouldLockout) 
    { 
     var user = UserManager.FindByEmailAsync(userName).Result; 

     if ((user.IsEnabled.HasValue && !user.IsEnabled.Value) || !user.IsEnabled.HasValue) 
     { 
      return Task.FromResult<SignInStatus>(SignInStatus.LockedOut); 
     } 

     return base.PasswordSignInAsync(userName, password, rememberMe, shouldLockout); 
    } 

您的情況可能有所不同,您可能不希望返回SignInStatus,但你的想法。

+1

如何在Identity 3.0中使用沒有ApplicationSignInManager或PasswordSignInAsync(...)的ASP.NET Core 1.0實現相同功能? – nam

+0

使用'.Result'是違反建議的,並且已知會在某些情況下導致死鎖,它也會阻止破壞整個異步點的線程。將'PasswordSignInAsync'方法標記爲'async'並等待'FindByEmailAsync'會更好。 – TKharaishvili

+1

這最大的問題是,如果他們已經登錄,它不會影響他們。特別是如果他們選中記住我複選框。如果他們定期訪問該網站,他們將永遠不需要登錄。我試圖弄清楚現有的鎖定邏輯是否可以用於此目的,以及是否更好地處理已登錄的用戶。 –

0

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

 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 
    } 

Source

+0

我可能會對此感到困惑,或者它沒有解決問題。我從代碼中獲取的信息將用於查看用戶是否處於鎖定狀態,該狀態可能來自不成功的登錄嘗試。這看起來只是在鎖定它們之前設置了註銷時間和失敗的登錄嘗試次數。我正在查看是否可以禁用該帳戶。做類似設置IsActive = false的操作。這樣他們就無法登錄期。當更新發生時,我會重置IsActive = true。類似的東西。我仍然會仔細查看代碼,看看它是否可以工作。 – Caverman

+0

我想拋出一個想法,我將嘗試實施禁用用戶。我將創建一個名爲「NoAccess」的角色。然後在我的控制器上,我不會將該角色包含在可以訪問任何ActionResult的角色中。在我的情況下,當有人註冊時,我會將其用作我的默認角色。我認爲這會照顧我的需求。 – Caverman

+0

但是,貌似我可能不得不在某個登錄失敗或使用上面的代碼之後將Identity設置爲鎖定。我很驚訝,微軟並沒有讓人們更容易看到被鎖定的人和/或解鎖他們的更簡單的方法。 – Caverman

3

對此做了一些研究,結果發現IdentityUser基類有一些與此主題相關的屬性。即:LockoutEnabledLockoutEndDateUtc

這足以使LockoutEnabledtrueLockoutEndDateUtc到將來的某一天,爲了使標準SignInManager.PasswordSignInAsync把它撿起來,沒有任何替代或自定義採取相應的行動。

如果您只想禁用用戶而不指定任何確切的重新激活日期,您可以將其設置爲DateTime.MaxValue

相關問題