2014-03-26 50 views
25

我正在尋找一種方法來禁用的,而不是從系統中刪除用戶,這是爲了保持相關數據的數據完整性。但似乎ASPNET身份只提供刪除帳戶。禁用用戶2.0

有一個新的鎖定功能,但它似乎閉鎖可以控制禁用的用戶,但是隻有特定數量的不正確的密碼嘗試後出鎖定用戶。

還有其他的選擇嗎?

回答

33

當您創建安裝了標識位的網站,您的網站將有一個名爲「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,但你的想法。

+0

這對我來說非常合適,謝謝! – Rob10e

+0

您是否需要檢查用戶是否存在以阻止user.IsEnabled上的NRE?我有以下內容:'if(user!= null &&!user.IsEnabled) { return Task.FromResult (SignInStatus.LockedOut); }'。我不檢查HasValue的原因是因爲我使IsEnabled成爲必填字段 –

9

您需要引入自己的標誌到自定義IdentityUser派生類和實現/執行自己的邏輯關於啓用/禁用和防止用戶如果禁用登錄。

+0

那麼賬戶鎖定怎麼樣。我大致看看,看起來我不應該用它來達到這個目的,對吧? – anIBMer

+0

在v2中,由於暴力破解密碼,對帳號鎖定提供了一些支持。 –

19

您不需要創建自定義屬性。訣竅是在身份用戶上設置 LockoutEnabled屬性並將代碼中的LockoutoutEndDateUtc設置爲未來日期以鎖定用戶。然後,調用UserManager.IsLockedOutAsync(user.Id)將返回false。

LockoutEnabledLockoutoutEndDateUtc都必須符合鎖定用戶的真實和未來日期標準。例如,如果LockoutoutEndDateUt的c值是2014-01-01 00:00:00.000LockoutEnabledtrue,則調用UserManager.IsLockedOutAsync(user.Id)仍將返回true。我可以看到微軟爲什麼這樣設計它,所以你可以設置一個用戶被鎖定多長時間的時間跨度。

但是,我認爲應該是LockoutEnabledtrue,那麼如果LockoutoutEndDateUtc爲空或未來的日期,那麼用戶應該被鎖定。這樣,你不必在你的代碼擔心設置兩個屬性(LockoutoutEndDateUtcNULL默認情況下)。你可以只設置LockoutEnabledtrue如果LockoutoutEndDateUtcNULL用戶被無限期鎖定。

+10

它已被提升了很多,但這個答案是錯誤的,因爲正如其他人所說的,你誤解了LockoutEnabled屬性。它表明用戶是否「可以被鎖定」。那裏應該是一個內置的屬性,簡稱爲「LockedOut」或類似的。更多信息:http://www.jamessturtevant.com/posts/ASPNET-Identity-Lockout/ – ozz

+0

LockoutEnabled爲true,並且將來的LockoutEndDateUtc意味着.IsLockedOutAsync爲TRUE,而不是false。 (1st ppg。)如果2014-01-01是過去的(就像它最初發布時那樣),.IsLockedOutAsync將「仍然」返回FALSE,不正確。第三點是一個模糊的概念。這是怎麼得到任何upvotes? – fortboise

+0

是的,你是對的,2014-01-01是錯誤的 - 它應該是未來的日期,比如DateTime.MaxValue。如果LockoutEnabled配置爲true,那麼當用戶檢查配置的MaxFailedAccessAttempts的數量時,LockoutEndate字段將從當前時間設置爲DefaultLockoutTimeSpan配置的任何值。正如你所提到的,我的第三個ppg有點含糊。簡而言之,我同意應該有一個bool字段來標記一個人是否被鎖定,並且不必手動編寫代碼將未來的日期設置到LockoutEnd字段來完成同樣的事情。 –

12

User的默認LockoutEnabled屬性不是指示用戶當前是否被鎖定的屬性。這表示使用者是否應該受到封鎖或沒有,一旦AccessFailedCount達到MaxFailedAccessAttemptsBeforeLockout值的屬性。即使用戶被鎖定,它也只是一種臨時措施,禁止用戶在LockedoutEnddateUtc期間的財產。因此,要永久禁用或暫停的用戶帳戶,您可能希望引入自己的標誌財產。

+0

完全同意,謝謝 – anIBMer

3

您可以使用這些類... ASP.NET標識的乾淨實現... 這是我自己的代碼。如果您希望主鍵的不同類型可以更改,則此處爲主鍵。

IdentityConfig.cs

public class ApplicationUserManager : UserManager<ApplicationUser, int> 
{ 
    public ApplicationUserManager(IUserStore<ApplicationUser, int> store) 
     : base(store) 
    { 
    } 
    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    { 
     var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get<ApplicationContext>())); 
     manager.UserValidator = new UserValidator<ApplicationUser, int>(manager) 
     { 
      AllowOnlyAlphanumericUserNames = false, 
      RequireUniqueEmail = true 
     }; 
     manager.PasswordValidator = new PasswordValidator 
     { 
      RequiredLength = 6, 
      RequireNonLetterOrDigit = true, 
      RequireDigit = true, 
      RequireLowercase = true, 
      RequireUppercase = true, 
     }; 
     manager.UserLockoutEnabledByDefault = false; 
     var dataProtectionProvider = options.DataProtectionProvider; 
     if (dataProtectionProvider != null) 
     { 
      manager.UserTokenProvider = 
       new DataProtectorTokenProvider<ApplicationUser, int>(
        dataProtectionProvider.Create("ASP.NET Identity")); 
     } 
     return manager; 
    } 
} 
public class ApplicationSignInManager : SignInManager<ApplicationUser, int> 
{ 
    public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : 
     base(userManager, authenticationManager) { } 
    public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user) 
    { 
     return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 
    } 
    public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context) 
    { 
     return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication); 
    } 
} 
public class ApplicationRoleManager : RoleManager<ApplicationRole, int> 
{ 
    public ApplicationRoleManager(IRoleStore<ApplicationRole, int> store) 
     : base(store) 
    { 
    } 
} 
public class ApplicationRoleStore : RoleStore<ApplicationRole, int, ApplicationUserRole> 
{ 
    public ApplicationRoleStore(ApplicationContext db) 
     : base(db) 
    { 
    } 
} 
public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, int, 
ApplicationLogin, ApplicationUserRole, ApplicationClaim> 
{ 
    public ApplicationUserStore(ApplicationContext db) 
     : base(db) 
    { 
    } 
} 

IdentityModel.cs

public class ApplicationUser : IdentityUser<int, ApplicationLogin, ApplicationUserRole, ApplicationClaim> 
{ 
    //your property 
    //flag for users state (active, deactive or enabled, disabled) 
    //set it false to disable users 
    public bool IsActive { get; set; } 
    public ApplicationUser() 
    { 
    } 
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, int> manager) 
    { 
     var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 
     return userIdentity; 
    } 
} 
public class ApplicationUserRole : IdentityUserRole<int> 
{ 
} 
public class ApplicationLogin : IdentityUserLogin<int> 
{ 
    public virtual ApplicationUser User { get; set; } 
} 
public class ApplicationClaim : IdentityUserClaim<int> 
{ 
    public virtual ApplicationUser User { get; set; } 
} 
public class ApplicationRole : IdentityRole<int, ApplicationUserRole> 
{ 
    public ApplicationRole() 
    { 
    } 
} 
public class ApplicationContext : IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationLogin, ApplicationUserRole, ApplicationClaim> 
{ 
    //web config connectionStringName DefaultConnection change it if required 
    public ApplicationContext() 
     : base("DefaultConnection") 
    { 
     Database.SetInitializer<ApplicationContext>(new CreateDatabaseIfNotExists<ApplicationContext>()); 
    } 
    public static ApplicationContext Create() 
    { 
     return new ApplicationContext(); 
    } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
     modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
    } 
} 

For Example Code

0

這一切其實我做的事:

var lockoutEndDate = new DateTime(2999,01,01); 
    UserManager.SetLockoutEnabled(userId,true); 
    UserManager.SetLockoutEndDate(userId, lockoutEndDate); 

這基本上是啓用鎖定(如果你不這樣做默認情況下,然後將鎖定結束日期設置爲一些遙遠的價值。