2015-10-05 23 views
6

Tôi đang cố gắng tìm cách tắt một người dùng trong Identity 2.0 và dường như không tìm thấy bất kỳ thông tin nào về nó.Làm thế nào để vô hiệu hóa một người dùng trong Identity 2.0?

Tôi muốn đặt cơ bản người dùng thành IsActive = false và muốn thực hiện ngay khi người dùng được tạo. Tuy nhiên, tôi cần một cách để thiết lập IsActive cho trang quản trị của chúng tôi. Tôi đã có điều này với thành viên ASP.Net nhưng tôi đang tìm cách để bí mật các trang web để MVC và Identity.

Đối với các yêu cầu của mình, chúng tôi yêu cầu mọi người tiếp tục và đăng ký tài khoản nhưng chúng tôi muốn tài khoản đó bị tắt theo mặc định. Sau đó, khi chúng tôi nhận được thanh toán để tham gia, chúng tôi sẽ quay lại và kích hoạt chúng. Chúng tôi cũng sử dụng nó để vô hiệu hóa người dùng khi đăng ký của họ đã hết và họ chưa gia hạn.

Có cách nào để vô hiệu hóa tài khoản mà không xóa tài khoản hoặc chỉ khóa chúng trong một khoảng thời gian X không? Cho đến nay tôi đã không tìm thấy bất kỳ cách nào chỉ cần vô hiệu hóa một người dùng trong Identity và tôi ngạc nhiên câu hỏi này đã không đi lên trước.

Trả lời

11

Khi bạn tạo một trang web với các bit nhận dạng cài đặt, trang web của bạn sẽ có một tập tin gọi là "IdentityModels.cs". Trong tệp này là một lớp được gọi là ApplicationUser kế thừa từ 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 

Có một liên kết tốt đẹp trong các ý kiến ​​đó, để dễ bấm here

Hướng dẫn này sẽ cho bạn biết chính xác những gì bạn cần làm thêm các thuộc tính tùy chỉnh cho người dùng của bạn.

Và thực sự, thậm chí không bận tâm khi xem hướng dẫn.

1) thêm một thuộc tính vào lớp ApplicationUser, ví dụ:

public bool? IsEnabled { get; set; } 

2) Thêm một cột có cùng tên trên bảng AspNetUsers trong DB của bạn.

3) bùng nổ, đúng vậy!

Bây giờ trong AccountController của bạn, bạn có một hành động ký như sau:

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) 

Tôi đã thêm IsEnabled = true vào việc tạo ra các đối tượng ApplicationUser. Giá trị bây giờ sẽ được duy trì trong cột mới của bạn trong bảng AspNetUsers.

Sau đó, bạn sẽ cần xử lý việc kiểm tra giá trị này như là một phần của quá trình đăng nhập, bằng cách ghi đè PasswordSignInAsync trong ApplicationSignInManager.

tôi đã làm nó như sau:

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

Mileage của bạn có thể thay đổi, và có thể bạn không muốn quay trở lại đó SignInStatus, nhưng bạn sẽ có được ý tưởng.

+1

Làm thế nào để bạn đạt được điều tương tự trong ASP.NET Core 1.0 với Identity 3.0 không có ApplicationSignInManager hoặc PasswordSignInAsync (...)? – nam

+0

Sử dụng '.Result' là chống lại các khuyến nghị và được biết là gây ra deadlocks trong một số trường hợp nhất định, nó cũng chặn luồng đánh bại toàn bộ điểm không đồng bộ. Sẽ tốt hơn nếu đánh dấu phương thức 'PasswordSignInAsync' là 'async' và chờ' FindByEmailAsync' thay thế. – TKharaishvili

+1

Vấn đề lớn nhất với điều này là nếu họ đã đăng nhập, nó sẽ không ảnh hưởng đến chúng. Đặc biệt nếu họ chọn hộp kiểm Ghi Nhớ Tôi. Nếu họ truy cập vào trang web một cách thường xuyên, họ sẽ không bao giờ cần phải đăng nhập. Tôi đang cố gắng tìm hiểu xem logic khóa hiện tại có thể được sử dụng cho điều này hay không và liệu có tốt hơn không khi xử lý người dùng đã đăng nhập . –

0

BướC# 1: Tạo cửa hàng người dùng tùy chỉnh triển khai 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) 
    { 
     //.. 
    } 
} 

BướC# 2: Thay vì UserManager, sử dụng lớp sau trong hành động đăng nhập/đăng xuất của bạn, chuyển trường hợp của cửa hàng người dùng tùy chỉnh của bạn.

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

VÍ DỤ

[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

Tôi có thể nhầm lẫn về điều này hoặc không giải quyết được câu hỏi. Những gì tôi lấy từ mã nó sẽ được sử dụng để xem nếu người dùng đang ở trong một trạng thái bị khóa mà có thể đến từ nỗ lực đăng nhập không thành công. Điều này có vẻ như nó chỉ đặt thời gian đăng xuất và số lần đăng nhập không thành công trước khi khóa chúng. Tôi đang tìm cách xem liệu tôi có thể vô hiệu hóa tài khoản không. Làm một cái gì đó như thiết lập IsActive = false. Bằng cách đó họ chỉ không thể đăng nhập trong thời gian. Khi gia hạn xảy ra tôi sẽ chỉ cần thiết lập lại IsActive = true. Một cái gì đó tương tự như vậy. Tôi vẫn sẽ xem xét mã nhiều hơn và xem nó có hoạt động hay không. – Caverman

+0

Tôi muốn đưa ra một ý tưởng mà tôi sẽ cố gắng triển khai để vô hiệu hóa người dùng. Tôi sẽ tạo ra một vai trò gọi là "NoAccess". Sau đó, trên bộ điều khiển của tôi, tôi sẽ không bao gồm vai trò đó như là một trong đó có thể nhận được bất kỳ ActionResult. Trong trường hợp của tôi, tôi sẽ sử dụng nó như là vai trò mặc định của tôi khi ai đó đăng ký. Tôi nghĩ rằng sẽ chăm sóc nhu cầu của tôi. – Caverman

+0

Tuy nhiên, có vẻ như tôi có thể không phải đặt Nhận dạng để khóa sau một số lần đăng nhập không thành công hoặc sử dụng mã ở trên. Tôi ngạc nhiên rằng Microsoft đã không làm cho nó dễ dàng hơn để xem ai đó đang bị khóa và/hoặc một cách dễ dàng hơn để mở khóa chúng. – Caverman

3

Đã thực hiện một số nghiên cứu về điều này và chỉ ra lớp cơ sở IdentityUser có một số thuộc tính liên quan đến chủ đề này. Cụ thể là: LockoutEnabledLockoutEndDateUtc.

Đó là đủ để thiết lập LockoutEnabled để trueLockoutEndDateUtc một số ngày trong tương lai để các tiêu chuẩn SignInManager.PasswordSignInAsync để nhặt nó lên và hành động phù hợp mà không cần bất kỳ ghi đè hoặc tùy chỉnh.

Và nếu bạn chỉ muốn vô hiệu hóa người dùng mà không chỉ định ngày chính xác của kích hoạt, bạn chỉ có thể đặt thành DateTime.MaxValue.

Các vấn đề liên quan