2016-04-21 25 views
8

Prima di tutto, io sono a conoscenza di questa domanda: MVC 5 AddToRole requires logout before it works?ASP.NET Identità, aggiungere un altro utente al ruolo istantaneamente (che non c'è bisogno di uscire e di nuovo)

e questo: What is ASP.NET Identity's IUserSecurityStampStore<TUser> interface?

quindi si prega di non contrassegnarlo come duplicato.

Sto cercando di aggiungere un altro utente a un ruolo (cioè l'utente stiamo aggiungendo al ruolo non è l'utente corrente. Se lo sono, la risposta alla prima domanda che ho legato alla è sufficiente.)

Come così:

IdentityResult result = await userManager.AddToRoleAsync(userID, roleName); 

le due situazioni che sto facendo questo sono: da una pagina di amministrazione, in cui l'utente corrente è l'amministratore; e un webhook protetto con l'autenticazione di base (in cui non vi è alcun utente corrente).

IL PROBLEMA: se l'utente a cui si applica questa modifica è connesso e utilizza l'app, ho bisogno della modifica "aggiungi al ruolo" per applicare immediatamente. Non dovrebbero dover disconnettersi e rientrare per far si che il cambiamento avvenga, e deve avvenire immediatamente.

Grazie a tutti.

MODIFICA: A proposito, User.IsInRole (roleName) richiede il logout e il login per riflettere sull'aggiunta al nuovo ruolo. UserManager.IsInRole (userID, roleName) non lo fa, perché (presumo) va direttamente alle tabelle del database per verificare. Ma se l'utente raggiunge un metodo di azione protetto con il ruolo a cui è appena stato aggiunto, deve ancora accedere di nuovo, il che è abbastanza giusto. Ancora curioso se c'è un modo per aggirare questo.

EDIT: Ecco il codice sorgente per l'attributo Autorizza: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/src/System.Web.Mvc/AuthorizeAttribute.cs

Esso utilizza User.IsInRole, che è essenzialmente il motivo per cui abbiamo bisogno di accedere nuovamente. Sembra che il metodo per eseguire l'override sia AuthorizeCore (HttpContextBase httpContext). Non sono coraggioso o abbastanza bravo per scherzare con questo in questo momento, ma se vuoi farlo, molte persone lo troveranno utile.

+0

Sono interessato a conoscere la risposta a questa domanda da quando mi sono chiesto – jamiedanq

risposta

4

A partire dalla parte inferiore della domanda. User.IsInRole() entra nel cookie utente e controlla quali ruoli sono memorizzati in quel cookie. Quindi richiede che il relogin per le modifiche abbia effetto. E sì, hai ragione nel dire che gli assegni UserManager.IsInRole() con il database, non con il cookie.

Per assicurarsi che le modifiche ai ruoli vengano applicate immediatamente, è necessario verificare la presenza di modifiche nei ruoli in ogni richiesta. Per fare questo in Startup.Auth.cs trovare questa linea:

OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
    validateInterval: TimeSpan.FromMinutes(0), // <-- This is zero. Check on every request 
    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)), 

Questo è il modo di un quadro di aggiornamento dei cookie. Per impostazione predefinita, validateInterval è impostato per 30 minuti. Se lo si imposta su zero, il sistema creerà un nuovo cookie con ruoli aggiornati su ogni richiesta. Questo potrebbe essere un carico di DB eccessivo se hai abbastanza utenti che colpiscono il tuo sistema contemporaneamente. Quindi aumenterei il tempo a 30 secondi-1-2 minuti.

Questa funzione è stata creata come un modo per disconnettere tutte le sessioni con una singola modifica della password. Ma funziona anche bene per i tuoi scopi.

+1

Ottima risposta! Mi è già venuto in mente quando ho trovato la tua risposta qui: http://stackoverflow.com/questions/25878218/asp-net-identity-2-0-sign-out-another-user, ma come dici tu, carico del database. Immagino solo test e non è un problema finché non è un problema. Ma sembra una soluzione piuttosto estrema per evitare un piccolo login. Grazie! – nmit026

+1

Bene, misurare il carico e profilare le richieste del DB e decidere se questo è un vantaggio o un problema. È possibile impostare l'intervallo di tempo su 5 minuti. Presto sarà sufficiente aggiornare i ruoli dal punto di vista dell'utente e non aggiungere molto carico extra. Ancora una volta, sto parlando di migliaia di utenti allo stesso tempo ... e questo è un bel problema! – trailmax

2

In ASP.NET Core, SignInManager.RefreshSignInAsync() risolve questo problema.

Problemi correlati