2010-07-19 13 views
6

Je l'ai mis en place un fournisseur de rôle personnalisé et configuré dans mon fichier web.config comme ceci:ASP .NET personnalisée RoleProvider ne respectant pas cacheRolesInCookie = « true »

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

J'ai surchargé la fonction GetRolesForUser dans mon fournisseur de rôle personnalisé, et je suis intervenu, et cela fonctionne très bien - charge jusqu'à 60 rôles pour l'utilisateur que je suis en train de tester. Cependant, j'ai remarqué que GetRolesForUser est appelé sur chaque requête qui appelle User.IsInRole. Dans d'autres applications que j'ai écrites, elle ne l'appelle qu'une fois, puis met en cache le résultat dans le cookie. Pour une raison quelconque, la mise en cache ne fonctionne pas pour cette application. Une quelconque idée du pourquoi?

Répondre

2

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

« La question de savoir quand mettre en cache (ou pas de cache) dans RolePrincipal est passé par un certain nombre d'itérations de conception, et nous avons finalement sur la mise en cache uniquement pour la méthode exposée par la IPrincipal interface (ie IsInRole). "

+0

Alors, quelle serait la meilleure façon de faire cela? Je veux que les rôles soient mis en cache dans le cookie. –

+0

Tester-et-erreur et choisir avec soin les méthodes à utiliser, je suppose. – Greg

+5

Le lien est cassé. –

1

La même chose est vraie pour moi. Il continue d'appeler GetRolesForUser()

+0

Voir la réponse de Joao, ça marche. – Lee

3

J'avais le même problème. Dans mon cas, le problème était que je mettais Context.User à GenericPrincipal et non RolePrincipal. Ainsi, au lieu de:

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

que ce soit réglé pour moi:

  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 
      } 

Les IsValidAuthCookie méthode vérifie nulle et vide:

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

MISE À JOUR: Après la mise à niveau MVC5 .NET 4.5 roleManager a cessé de fonctionner (ne pas enregistrer les rôles dans un cookie) et a dû le sauvegarder moi-même:

 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); 
     } 
    } 

Placez ce code sur AuthenticationFilter et l'enregistrer au niveau mondial. Voir here.

+0

J'ai cherché des heures sur ce problème et cela l'a corrigé! Merci beaucoup d'avoir posté cela! Pouvez-vous répondre à une question, quelle est la référence pour la méthode IsValidAuthCookie ou quelle est la classe dans laquelle le code écrit implémente cette méthode? –

+0

Merci beaucoup pour cette réponse. C'est la seule solution qui traite de la mise en cache qui ne fonctionne plus dans MVC 5 lorsque vous implémentez votre Rôle RoleProvider. J'ai mis ceci dans mon propre attribut d'autorisation à la place. – Lee