2012-12-12 20 views
8

L'applicazione MVC utilizza il ruolo dell'utente in più posizioni durante le singole richieste di pagina. La mia domanda è se il predefinito SqlRoleProvider memorizza nella cache i ruoli dell'utente corrente per tutta la durata di una richiesta di pagina?La cache del provider di ruoli viene memorizzata per richiesta?

Per esempio, faccio uso di ruoli negli attributi sui metodi controller:

[Authorize(Roles = "Admin")] 

e codice personalizzato

if (user.IsInRole(MembershipRole.Admin)) 
{ 
    // Do something 
} 
else if (user.IsInRole(MembershipRole.Printer)) 
{ 
    // Do something else 
} 

Se il provider di ruoli non memorizza nella cache i ruoli, è la soluzione migliore per scrivere un fornitore di ruolo personalizzato che eredita da quello predefinito e sovrascrive i metodi per ottenere i ruoli una volta e li memorizza nella cache per la durata della richiesta? Questo può essere fatto in modo che sia l'attributo Authorize sia il mio codice utilizzeranno i ruoli memorizzati nella cache?

(Nel caso ve lo stiate chiedendo, non voglio usare l'opzione web.config cacheRolesInCookie per memorizzare i ruoli nei cookie).

Grazie in anticipo per eventuali suggerimenti.

[Modifica per includere i dettagli innescate dalla risposta di Joe]

Ho decompilato System.Web.Mvc.AuthorizeAttribute e il metodo AuthorizeCore chiama il seguente metodo per ogni ruolo da controllare:

httpContext.User.IsInRole 

Poi scrutando System.Web.Security.RolePrincipal (che è ciò che "utente" è al di sopra) sia le modalità di seguito effettivamente utilizzare una copia cache dei ruoli dell'Utente (o popola la cache se vuoto):

La cache è memorizzata come campo sull'utente, quindi la sua durata è per la durata della richiesta.

I metodi trovano i ruoli utilizzando:

Roles.Providers[this._ProviderName].GetRolesForUser(this.Identity.Name) 

così sarà utilizzare qualsiasi provider di ruoli che avete scelto per l'applicazione (predefinito o personalizzato).

risposta

6

Se si utilizza un RoleProvider in un'applicazione ASP.NET o ASP.NET MVC, quindi HttpContext.User farà riferimento a uno RolePrincipal che esegue la cache dei ruoli per la durata della richiesta.

Tuttavia, in un servizio WCF che utilizza i ruoli ASP.NET:

<behavior ...> 
    <serviceAuthorization principalPermissionMode ="UseAspNetRoles" 
        roleProviderName ="MyRoleProvider" /> 
</behavior> 

questo non è vero: invece HttpContext.User sarà riferimento alla classe interna System.ServiceModel.Security.RoleProviderPrincipal, che non memorizza ruoli: invece chiama sempre RoleProvider.IsUserInRole.

I RoleProvider pronte all'uso non eseguono alcuna memorizzazione nella cache, pertanto ciò può comportare connessioni ripetute all'archivio dati sottostante. Mi sembra una deficienza: sarebbe stato facile memorizzare i ruoli nel primo accesso.

è la soluzione migliore per scrivere un fornitore di ruolo personalizzato che eredita da quello predefinito e sostituire i metodi per ottenere i ruoli una volta e memorizzarli nella cache per la durata della richiesta?

Non necessario per ASP.NET o ASP.NET MVC, ma potrebbe essere previsto per WCF. Caching per la durata della Richiesta presumibilmente utilizzerà HttpContext.Items, quindi introdurrà una dipendenza dall'esistenza di HttpContext, ma questo non è necessariamente un problema tranne che per rendere più difficile il test dell'unità.

Questo può essere fatto in modo che sia l'attributo Authorize sia il mio codice utilizzeranno i ruoli memorizzati nella cache?

Se si configura la vostra abitudine RoleProvider in web.config non c'è più niente che devi fare in modo che l'attributo Authorize lo userà.

+2

Grazie per i vostri pensieri. La documentazione MSDN su RolePrincipal dice "Se CacheRolesInCookie è falso, l'oggetto RolePrincipal ricerca sempre l'appartenenza al ruolo utilizzando il provider di ruoli.". Quando si dice che RolePrincipal "mette in cache i ruoli per tutta la durata della richiesta" posso chiedere come lo si conosce (riflessione, SQL profiling, documentazione, ecc.), In quanto sembra contraddire MSDN? – Appetere

+0

@Steve, lo so osservando l'implementazione (Lutz Reflector o ILSpy), e anche dall'esperienza di implementazione di provider personalizzati. Ciò non contraddice MSDN: RolePrincipal ricerca il membro membeship utilizzando il provider di ruoli, chiama RoleProvider.GetRolesForUser, ma lo chiama solo una volta per richiesta, memorizzando nella cache il risultato in un campo HybridDictionary. RoleProviderPrincipal di WCF non chiama RoleProvider.GetRolesForUser, ma chiama sempre RoleProvider.IsInRole e non implementa alcuna memorizzazione nella cache dei ruoli. – Joe

+0

Grazie per quello. Ho seguito il tuo approccio e decompilato le assemblee rilevanti per vedere cosa succede realmente. Aggiunti alcuni dettagli alla mia domanda originale da aggiungere alla tua risposta. – Appetere

Problemi correlati