2015-10-05 31 views
6

Próbuję znaleźć sposób na wyłączenie użytkownika w tożsamości 2.0 i nie można znaleźć żadnych informacji na ten temat.Jak wyłączyć użytkownika w tożsamości 2.0?

Chciałbym zasadzie ustawić użytkownikowi IsActive = false i wolałby zrobić to tak szybko, jak użytkownik jest tworzony. Potrzebuję jednak sposobu na ustawienie IsActive dla naszej strony Admin. Mam już to z członkostwa ASP.Net, ale szukam, aby ukryć stronę do MVC i tożsamości.

Dla moich wymagań prosić ludzi, aby iść do przodu i zarejestrować konto, ale chcemy być domyślnie wyłączone. Wtedy, gdy otrzymamy zapłatę za dołączenie, wrócimy i udostępnimy je. Używamy go również do wyłączania użytkowników, gdy ich subskrypcja się skończyła i nie odnowili.

Czy istnieje sposób, aby zablokować konto bez usuwania go lub tylko ich blokowania na kwotę X czasu? Do tej pory nie znalazłem żadnego sposobu na wyłączenie użytkownika w Tożsamości i jestem zaskoczony, że to pytanie nie pojawiło się wcześniej.

Odpowiedz

11

Podczas tworzenia strony z bitami tożsamości zainstalowanych, witryna będzie mieć plik o nazwie "IdentityModels.cs". W tym pliku znajduje się klasa o nazwie ApplicationUser, która dziedziczy z 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 

Jest ładny ogniwo w tamtejszych komentarzach, dla ułatwienia kliknij here

Ten poradnik powie Ci dokładnie to, co trzeba zrobić, aby dodać właściwości niestandardowe dla użytkownika.

I rzeczywiście, nawet nie patrząc na kursie.

1) dodać obiekt do klasy ApplicationUser, np:

public bool? IsEnabled { get; set; } 

2) dodać kolumny o tej samej nazwie na stole AspNetUsers w swojej DB.

3) boom, to wszystko!

Teraz w AccountController masz działanie rejestru następująco:

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) 

Dodałem IsEnabled = true na utworzenie obiektu ApplicationUser. Wartość będzie teraz zachowana w nowej kolumnie w tabeli AspNetUsers.

Będziesz wtedy musiał zająć się sprawdzenie tej wartości jako część procesu logowania, nadrzędnymi PasswordSignInAsync w ApplicationSignInManager.

zrobiłem to w następujący sposób:

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

Twój przebieg mogą się różnić, a może nie chcieć, aby powrócić że SignInStatus, ale masz pomysł.

+1

Jak osiągnąć to samo w ASP.NET Core 1.0 z Identity 3.0, który nie ma ApplicationSignInManager lub PasswordSignInAsync (...)? – nam

+0

Używanie '.Result' jest niezgodne z zaleceniami i wiadomo, że powoduje zakleszczenia w niektórych scenariuszach, blokuje również wątek pokonujący cały punkt asynchroniczny. Lepiej byłoby oznaczyć metodę 'PasswordSignInAsync' jako' async' i zamiast tego oczekiwać 'FindByEmailAsync'. – TKharaishvili

+1

Największym problemem jest to, że jeśli są już zalogowani, nie wpłynie to na nich. Zwłaszcza jeśli zaznaczyli pole wyboru Zapamiętaj mnie. Jeśli regularnie odwiedzają witrynę, nigdy nie będą musieli się logować. Staram się dowiedzieć, czy można do tego wykorzystać istniejącą logikę blokowania i czy jest ona lepsza w obsłudze użytkowników, którzy są już zalogowani. . –

0

Krok 1: Tworzenie sklepu użytkownika niestandardowego, który implementuje 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) 
    { 
     //.. 
    } 
} 

Krok 2: Zamiast UserManager należy stosować następujące klasy w swojej logowania/wylogowania działania, przechodząc to wystąpienie niestandardowego sklepu użytkownika.

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

Przykład

[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

Może się to zdezorientować lub nie odpowiada na pytanie. To, co pobieram z kodu, który byłby używany do sprawdzenia, czy użytkownik jest w stanie Zablokowania, który byłby wynikiem nieudanych prób logowania. Wygląda na to, że ustawia tylko czas wylogowania i liczbę nieudanych prób logowania przed ich zablokowaniem. Czekam, czy mogę po prostu wyłączyć konto. Robi coś w rodzaju ustawienia IsActive = false. W ten sposób po prostu nie mogą się zalogować. Kiedy nastąpi odnowienie, po prostu zresetuję IsActive = true. Coś podobnego do tego. Wciąż będę przeglądał kod i sprawdzał, czy zadziała. – Caverman

+0

Chciałem rzucić pomysł, który zamierzam wprowadzić w celu wyłączenia użytkownika. Zamierzam stworzyć rolę o nazwie "NoAccess". Wtedy na moich kontrolerach nie uwzględnię tej roli jako takiej, która może dostać się do dowolnego ActionResult. W moim przypadku użyję tego jako domyślnej roli, gdy ktoś zarejestruje się. Myślę, że zadba o moje potrzeby. – Caverman

+0

Wygląda jednak na to, że nie muszę ustawiać tożsamości na blokadę po pewnym nieudanym logowaniu lub użyć powyższego kodu. Jestem zaskoczony, że Microsoft nie ułatwił spojrzenia na kogoś, kto został zablokowany i/lub łatwiejszy sposób na ich odblokowanie. – Caverman

3

Dokonałem pewnych badań na ten temat i okazało się, że klasa bazowa IdentityUser ma pewne właściwości związane z tym tematem. Mianowicie: LockoutEnabled i LockoutEndDateUtc.

To wystarczy ustawić LockoutEnabled do true i LockoutEndDateUtc pewnym terminie w przyszłości w celu standardowej SignInManager.PasswordSignInAsync aby go podnieść i podjąć odpowiednie działania bez nadpisania lub dostosowań.

Jeśli chcesz wyłączyć użytkownika bez podania dokładnej daty reaktywacji, możesz ustawić go na DateTime.MaxValue.