2010-07-19 7 views
6

ich einen benutzerdefinierten Rollenanbieter implementiert haben, und so konfiguriert ist es in meinem web.config-Datei wie folgt:ASP .NET Custom Roleprovider nicht respektiert CacheRolesInCookie = "true"

<roleManager enabled="true" defaultProvider="TDRoleProvider" cacheRolesInCookie="true"> 
    <providers> 
    <clear/> 
    <add name="TDRoleProvider" type="TDRoleProvider"/> 
    </providers> 
</roleManager> 

ich die GetRolesForUser Funktion außer Kraft gesetzt habe in meinem benutzerdefinierten Rollenanbieter, und ich bin hineingegangen, und es funktioniert gut - lädt 60 Rollen für den Benutzer, mit dem ich teste. Ich habe jedoch bemerkt, dass der GetRolesForUser bei jeder Anfrage aufgerufen wird, die User.IsInRole aufruft. In anderen Apps, die ich geschrieben habe, wird es nur einmal aufgerufen und speichert dann das Ergebnis im Cookie. Aus irgendeinem Grund funktioniert das Caching für diese App nicht. Irgendwelche Ideen, warum?

Antwort

2

http://connect.microsoft.com/VisualStudio/feedback/details/104688/rolemanager-cacherolesincookie-option-does-not-work

„Die Frage, wann (oder nicht Cache) zwischenzuspeichern in Roleprincipal durch eine Reihe von Design-Iterationen ging, und wir schließlich auf nur Caching für das Verfahren durch die freiliegende siedelten IPrincipal Schnittstelle (dh IsInRole). "

+0

Also, was wäre ein besserer Weg, dies zu tun? Ich möchte, dass die Rollen im Cookie zwischengespeichert werden. –

+0

Trial-and-Error und sorgfältig zu wählen, welche Methoden zu verwenden, denke ich. – Greg

+5

Die Verbindung ist unterbrochen. –

1

Das gleiche gilt für mich. Es hält Aufruf GetRolesForUser()

+0

Sieh Joao Antwort, es funktioniert. – Lee

3

Ich hatte das gleiche Problem. In meinem Fall war das Problem, dass ich Context.User auf GenericPrincipal und nicht auf RolePrincipal setzte. Also statt:

this.Context.User = new GenericPrincipal(customIdentity, roles); 

das für mich festgelegt:

  HttpCookie roleCookie = this.Context.Request.Cookies[Roles.CookieName]; 
      if (IsValidAuthCookie(roleCookie)) 
      { 
       this.Context.User = new RolePrincipal(customIdentity, roleCookie.Value); 
      } 
      else 
      { 
       this.Context.User = new RolePrincipal(customIdentity); 
       var x = this.Context.User.IsInRole("Visitor"); // do this to cache the results in the cookie 
      } 

Die IsValidAuthCookie Methode überprüft, für null und leer:

private static bool IsValidAuthCookie(HttpCookie authCookie) 
    { 
     return authCookie != null && !String.IsNullOrEmpty(authCookie.Value); 
    } 

UPDATE: Nach dem Upgrade auf MVC5 .NET 4.5 roleManager funktioniert nicht mehr (Rollen im Cookie nicht gespeichert) und musste es selbst speichern:

 HttpCookie roleCookie = filterContext.HttpContext.Request.Cookies[Roles.CookieName]; 
     if (IsValidAuthCookie(roleCookie)) 
     { 
      filterContext.Principal = new RolePrincipal(customIdentity, roleCookie.Value); 
      RolePrincipal rp = (RolePrincipal)filterContext.Principal; 
      if (!rp.IsRoleListCached) // check if roles loaded properly (if loads old cookie from another user for example, roles won't be loaded/cached). 
      { 
       // roles not loaded. Delete and save new 
       Roles.DeleteCookie(); 
       rp.IsInRole("Visitor"); // load Roles 
       SaveRoleCookie(rp, filterContext); 
      } 

     } 
     else 
     { 
      filterContext.Principal = new RolePrincipal(customIdentity); 
      filterContext.Principal.IsInRole("Visitor"); // do this to cache the results in the cookie. 
      SaveRoleCookie(filterContext.Principal as RolePrincipal, filterContext); 
     } 

Save the roleCookie

private void SaveRoleCookie(RolePrincipal rp, AuthenticationContext filterContext) 
    { 
     string s = rp.ToEncryptedTicket(); 
     const int MAX_COOKIE_LENGTH = 4096; 
     if (string.IsNullOrEmpty(s) || s.Length > MAX_COOKIE_LENGTH) 
     { 
      Roles.DeleteCookie(); 
     } 
     else 
     { 
      HttpCookie cookie = new HttpCookie(Roles.CookieName, s); 
      cookie.HttpOnly = true; 
      cookie.Path = Roles.CookiePath; 
      cookie.Domain = Roles.Domain; 
      if (Roles.CreatePersistentCookie) 
       cookie.Expires = rp.ExpireDate; 
      cookie.Secure = Roles.CookieRequireSSL; 
      filterContext.HttpContext.Response.Cookies.Add(cookie); 
     } 
    } 

Platzieren Sie diesen Code auf AuthenticationFilter und es global registrieren. Siehe here.

+0

Ich habe stundenlang zu diesem Thema gesucht und dies behoben! Vielen Dank für das Posten! Können Sie eine Frage beantworten, was ist die Referenz für die Methode IsValidAuthCookie oder welche Klasse ist der geschriebene Code, der diese Methode implementiert? –

+0

Dank dieser Antwort hat sehr geholfen. Dies ist die einzige Lösung, die das Caching in MVC 5 nicht mehr unterstützt, wenn Sie Ihren rohen RoleProvider implementieren. Ich stelle dies stattdessen in mein eigenes Autorisierungsattribut. – Lee