2017-02-21 19 views
9

Próbuję znaleźć sposób na dostarczenie administratorowi aplikacji, którą rozwijam, skutecznego sposobu na szybkie zablokowanie użytkownika, który opuścił firmę lub został zidentyfikowany jako zachowujący się w sposób, który uzasadniałby natychmiastowe blokowanie lub korzystanie z aplikacji.W rdzeniu tożsamości ASP.net (UserManager i SignInManager) możliwe jest natychmiastowe zablokowanie użytkownika?

Do tej pory wygląda na to, że mogę;

//enable the account to be locked out 
_userManager.SetLockoutEnabledAsync(ApplicationUser user, true); 

//Set an arbitrary date way into the future to lock them out until I want to unlock them 
_userManager.SetLockoutEndDateAsync(ApplicationUser user, "01/01/2060"); 

Jednak powyższe nie rozwiąże problemu, jeśli użytkownik ma plik cookie z czasem wygaśnięcia wynoszącym 30 minut. Oznacza to, że użytkownik może nadal korzystać z aplikacji, jeśli są już uwierzytelnione i znajdują się w domyślnym czasie używanym do przechowywania plików cookie.

Czy istnieje metoda zarządzania użytkownikami, która zmienia "sprawdzanie", z którego pochodzi plik cookie? Zakładam, że tag atrybutu [Authorize] sprawdza ciasteczko pod kątem czegoś w obrębie Tożsamości, którego nie ma w tabeli. Zastanawiasz się, jak zmienić wartości "sprawdź", aby nie pasowały do ​​sesji cookie?

+0

W strukturze tożsamości nie ma nic, co mogłoby unieważnić takiego użytkownika. Napisanie jakiegoś oprogramowania pośredniego nie powinno być zbyt trudne. – DavidG

+0

@DavidG Dzięki, jaki jest pomysł, co dokładnie mogę zaktualizować, aby po napotkaniu [Autoryzuj] wartości różniące się sprawdzaniem poprawności? – JReam

Odpowiedz

6

Można to zrobić za pomocą oprogramowania pośredniego, które działa w przypadku każdego żądania. Najpierw utworzyć klasy middleware, coś takiego:

public class UserDestroyerMiddleware 
{ 
    private readonly RequestDelegate _next; 

    public UserDestroyerMiddleware(RequestDelegate next) 
    { 
     _next = next; 
    } 

    public async Task Invoke(HttpContext httpContext, 
     UserManager<ApplicationUser> userManager, 
     SignInManager<ApplicationUser> signInManager) 
    { 
     if (!string.IsNullOrEmpty(httpContext.User.Identity.Name)) 
     { 
      var user = await userManager.FindByNameAsync(httpContext.User.Identity.Name); 

      if (user.LockoutEnd > DateTimeOffset.Now) 
      { 
       //Log the user out and redirect back to homepage 
       await signInManager.SignOutAsync(); 
       httpContext.Response.Redirect("/"); 
      } 
     } 
     await _next(httpContext); 
    } 
} 

i przedłużenie aby łatwo skonfigurować:

public static class UserDestroyerMiddlewareExtensions 
{ 
    public static IApplicationBuilder UseUserDestroyer(this IApplicationBuilder builder) 
    { 
     return builder.UseMiddleware<UserDestroyerMiddleware>(); 
    } 
} 

a teraz w swojej metodzie Configure w Startup.cs dodać ten wiersz po Identity został skonfigurować:

app.UseUserDestroyer(); 

Teraz to oprogramowanie pośrednie powinno działać przy każdym żądaniu sprawdzającym, czy użytkownik powinien się wylogować. Możesz usprawnić ten proces, sprawiając, że nie trafi on do bazy danych przy każdym żądaniu i zamiast tego użyje jakiejś buforowanej listy ostatnio usuniętych użytkowników.

+0

Ładne rozwiązanie! Jestem zaskoczony, że nie ma możliwości zmiany wartości, pod jaką wartość pliku cookie zostanie odrzucona, aby można było zastosować normalny proces autoryzacji. Byłoby miło wiedzieć, co [autoryzuje] faktycznie robi pod kołdrą, ale nie mogę znaleźć żadnej dobrej dokumentacji poza "implementacją". – JReam

+0

Cóż, ciasteczko jest przechowywane w przeglądarce użytkownika, więc nigdy nie będziesz w stanie tego zmienić. Kod rzeczy takich jak ['AuthorizeAttribute'] (https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authorization/AuthorizeAttribute.cs) jest dostępny na GitHub, na pewno warto się przyjrzeć tam. – DavidG

+0

Pracuję nad aplikacją, która wykorzystuje autoryzację opartą na pliku cookie tożsamości 3, role, które odwzorowują na użytkowników i roszczenia do ról, w których polityka sprawdza roszczenia. Roszczenia są przechowywane w pliku cookie, w którym moja sesja cookie jest domyślna 30 minut. Jeśli zmienię rolę użytkownika, ten użytkownik nie może uzyskać dostępu do zasobów zapakowanych przez zasady z roszczeniami, że rola ma ważność do momentu wygaśnięcia ciasteczka użytkownika lub wylogowania i ponownego zalogowania. Byłoby miło, gdyby Tożsamość posiadała metodę _userManager.LogOutUserAsync (użytkownik). W ten sposób plik cookie zostanie zresetowany z nowymi wartościami z roszczeń +/- oraz blokadą. – JReam

0

Muszę myśleć o tym trochę więcej dzięki apelacji @ DavidG.

W prawie każdym kontrolerze, muszę uzyskać użytkownika, aby rozwiązać, jeśli użytkownik należy do grupy użytkowników hosta, określonej grupy użytkowników lokatora, i/lub dodać użytkownika jako redaktora w polu takim jak EditedBy jeśli pracuję z obiektem, który jest aktualizowany.

To dało mi do myślenia, że ​​zamiast;

var user = _userManager.GetUserByEmail(User.Identity.Name); 

var hostId = user.HostId; 

lub

var tenantId = user.TenantId; 

lub

var EditedBy = user.Email; 

mogę utworzyć klasę, która pobiera od użytkownika, ale również sprawdza obiekt użytkownika o zmianie stanu, takich jak "LockoutEnd> Dzisiejszy, lub ClaimsHaveBeenUpdated.

Oto inne podejście, które wymyśliłem, aby złagodzić dwa wywołania db na każde żądanie.

Metoda Controller

var user = _userManager.GetUserByEmail(User.Identity.Name); 

Repository

public async Task<ApplicationUser> GetUserByEmailAsync(string email) 
    { 
     var user = await _context.Users.FirstOrDefaultAsync(x=>x.Email.Equals(email)); 

     if(user.LockoutEnd > DateTimeOffset.Now) 
     { 
      await _signInManager.SignOutAsync(); 
     } 
     if (user.CookieStateHasChanged) 
     { 
      user.CookieStateHasChanged = false; 
      await _userManager.UpdateAsync(user); 
      await _signInManager.RefreshSignInAsync(user); 

     } 
     return user; 
    } 

Niestety ja już wywołanie dB dla użytkownika w każdej metodzie kontroler GET rozwiązać jeśli jego lokatora lub hosta użytkownika przed wykonaniem dodatkowej działalności logika. Dodając powyższy dodatkowy kod do metody GetUserByEmailAsync w moim repo, które włączam do konstruktora kontrolerów, mogę również obsłużyć zmiany roszczenia użytkownika przez odświeżenie pliku cookie lub wylogowanie użytkownika, jeśli są one zablokowane.

Pamiętaj, że jeśli role zostaną zmienione, będę musiał zaktualizować użytkownika.CookieStateHasChange = true.

A gdy użytkownik jest "wyłączony" za pośrednictwem interfejsu użytkownika, aktualizuję użytkownika.LockoutEnd na 10 lat + w dół drogi.

0

Myślę, że raczej prostym podejściem byłoby stworzenie filtra do tego. Może dziedziczenie atrybutu Authorize i sprawdzanie flagi blokady dla bieżącego użytkownika. Będzie działać również w poprzednich wersjach asp.net.

Powiązane problemy