2012-12-12 16 views
8

Moja aplikacja MVC korzysta z roli użytkownika w wielu miejscach podczas poszczególnych żądań strony. Moje pytanie brzmi, czy domyślny SqlRoleProvider buforuje bieżące role użytkownika przez całe życie żądania strony?Czy pamięć podręczna dostawcy roli na żądanie?

Na przykład, wykorzystanie role w atrybutach na metodach Kontroler:

[Authorize(Roles = "Admin")] 

i niestandardowy kod

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

Jeśli Provider rola nie buforują role, jest najlepszym rozwiązaniem, aby napisać niestandardowy dostawca roli, który dziedziczy po domyślnym, i zastępuje metody, aby uzyskać role raz i buforować je na czas trwania żądania? Czy można to zrobić w taki sposób, że zarówno atrybut Authorize, jak i mój własny kod wykorzystają role z pamięci podręcznej?

(W przypadku, gdy zastanawiasz się, nie chcę użyć opcji cacheRolesInCookie web.config buforowanie role w cookie).

Z góry dziękujemy za wszelkie sugestie.

[Edytuj zawierać dane wywołane z odpowiedzią Joe]

I dekompilowana System.Web.Mvc.AuthorizeAttribute i metoda AuthorizeCore wywołuje następujący sposób każda rola należy sprawdzić:

httpContext.User.IsInRole 

Następnie zaglądając do System.Web.Security.RolePrincipal (co oznacza "Użytkownik" powyżej) obie poniższe metody rzeczywiście używają buforowanej kopii ról użytkownika (lub zapełniają pamięć podręczną, jeśli są puste):

Pamięć podręczna jest przechowywana jako pole na Użytkownika, więc jego życie jest na czas wniosku.

Sposoby znalezienia ról przy użyciu:

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

więc użyje cokolwiek rola dostawcy wybrałeś dla aplikacji (domyślnej lub niestandardowej).

Odpowiedz

6

Jeśli używasz RoleProvider w ASP.NET lub aplikacji ASP.NET MVC, następnie HttpContext.User będzie odwoływać się RolePrincipal który robi role pamięci podręcznej dla życia wniosku.

Jednak w usług WCF, który używa ról ASP.NET:

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

nie jest to prawdą: zamiast HttpContext.User będzie odwoływać klasę wewnętrzną System.ServiceModel.Security.RoleProviderPrincipal, który nie buforuje role: zamiast zawsze wywołuje RoleProvider.IsUserInRole.

out-of-the-box RoleProviders nie rób żadnych buforowanie, więc może to doprowadzić do wielokrotnych połączeń podstawowej magazynu danych. Wydaje mi się, że był to dla mnie niedobór: łatwo byłoby zapamiętać role przy pierwszym dostępie.

jest najlepszym rozwiązaniem, aby napisać niestandardowego dostawcy roli, która dziedziczy z domyślnego, a zastępują metod, aby uzyskać ról raz buforować je na czas prośbę?

Nie jest to konieczne dla ASP.NET lub ASP.NET MVC, ale może być przewidziane dla WCF. Buforowanie dla czasu trwania żądania będzie prawdopodobnie używać HttpContext.Items, więc wprowadzi zależność od istnienia HttpContext, ale niekoniecznie jest to problemem, z wyjątkiem trudniejszych testów jednostkowych.

Czy można to zrobić w taki sposób, że zarówno atrybut Authorize, jak i mój własny kod wykorzystają role z pamięci podręcznej?

przypadku konfigurowania zwyczaj RoleProvider w web.config nic więcej trzeba zrobić tak, że atrybut Authorize będą go używać.

+2

Dzięki za twoje myśli. Dokumentacja MSDN na RolePrincipal mówi: "Jeśli CacheRolesInCookie jest fałszywe, obiekt RolePrincipal zawsze wyszukuje członkostwo roli za pomocą dostawcy roli.". Kiedy mówisz, że RolePrincipal "robi role pamięci podręcznej przez całe życie żądania", czy mogę zapytać, skąd to wiesz (odbicie, profilowanie SQL, dokumentacja itp.), Ponieważ wydaje się to być sprzeczne z MSDN? – Appetere

+0

@Steve, wiem o tym, patrząc na implementację (Lutz Reflector lub ILSpy), a także z doświadczenia w implementacji niestandardowych dostawców. Nie jest to jednak sprzeczne z MSDN: RolePrincipal sprawdza rolę roli przy użyciu dostawcy roli - wywołuje RoleProvider.GetRolesForUser, ale wywołuje go tylko raz dla każdego żądania, buforując wynik w polu HybridDictionary. RoleProviderPrincipal WCF nie wywołuje RoleProvider.GetRolesForUser, zamiast tego zawsze wywołuje RoleProvider.IsInRole i nie implementuje buforowania ról. – Joe

+0

Dzięki za to. Postępowałem zgodnie z twoim podejściem i dekompilowałem odpowiednie złożenia, aby zobaczyć, co się właściwie dzieje. Dodano kilka szczegółów do mojego pierwotnego pytania, aby dodać je do swojej odpowiedzi. – Appetere

Powiązane problemy