2010-06-06 14 views
4

c'est le code actuel dans ASP.NET MVC2 (RTM) System.Web.Mvc.AuthorizeAttribute classe: -Quelqu'un peut-il m'expliquer ce bloc de code ASP.NET MVC, s'il vous plaît?

public virtual void OnAuthorization(AuthorizationContext filterContext) 
{ 
    if (filterContext == null) 
    { 
     throw new ArgumentNullException("filterContext"); 
    } 
    if (this.AuthorizeCore(filterContext.HttpContext)) 
    { 
     HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache; 
     cache.SetProxyMaxAge(new TimeSpan(0L)); 
     cache.AddValidationCallback(
      new HttpCacheValidateHandler(this.CacheValidateHandler), null); 
    } 
    else 
    { 
     filterContext.Result = new HttpUnauthorizedResult(); 
    } 
} 

donc si je suis « autorisé », puis faire des trucs de mise en cache, sinon jeter une réponse 401 non autorisée.

Question: Que font ces 3 lignes de mise en cache?

cheers :)

+0

qu'en pensez-vous? –

+1

Eh bien, je suppose que c'est mettre en cache pour .. le contexte .. qui signifie alors la réponse. Mais, cet âge est .. maintenant? et je ne comprends pas ce que ce rappel est/fait/comment ou quand il a tiré. –

Répondre

15

Ce code existe pour vous permettre de placer à la fois [OutputCache] et [Authorize] ensemble sur une action sans courir le risque d'avoir une réponse qui a été générée pour un utilisateur autorisé mis en cache et servi à un utilisateur non autorisé.

Voici le commentaire du code source de AuthorizeAttribute.cs:

Puisque nous l'autorisation d'effectuer au niveau d'action, l'autorisation code est exécuté après la mise en cache du module de sortie . Dans le pire des cas, cela pourrait permettre à un utilisateur autorisé de mettre en cache la page , puis un utilisateur non autorisé sera plus tard mis en cache sur la page. Nous travaillons ce en disant fondés de pouvoir mettre en cache la page sensible, nous accrocher notre code d'autorisation personnalisée dans le mécanisme de mise en cache afin que nous ayons le dernier mot sur une page doit être servi à partir du cache.

Alors, que fait cet attribut? Il désactive d'abord la mise en cache du proxy de cette réponse, car les proxys ne peuvent pas déterminer correctement quels utilisateurs sont ou ne sont pas autorisés à l'afficher. Et si un proxy sert la réponse à un utilisateur non autorisé, c'est une très mauvaise chose.

Maintenant, qu'en est-il de AddValidationCallback? Dans ASP.NET, le module de mise en cache de sortie connecte les événements qui exécutent avant le le gestionnaire HTTP. Comme MVC est vraiment un gestionnaire HTTP spécial, cela signifie que si le module de cache de sortie détecte que cette réponse a déjà été mise en cache, le module servira simplement la réponse directement à partir du cache sans passer par le pipeline MVC. Ceci est également potentiellement une très mauvaise chose si le cache de sortie sert la réponse à un utilisateur non autorisé.

maintenant un coup d'oeil de plus près CacheValidateHandler:

private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) { 
    validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); 
} 

// This method must be thread-safe since it is called by the caching module. 
protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext) { 
    if (httpContext == null) { 
     throw new ArgumentNullException("httpContext"); 
    } 

    bool isAuthorized = AuthorizeCore(httpContext); 
    return (isAuthorized) ? HttpValidationStatus.Valid : HttpValidationStatus.IgnoreThisRequest; 
} 

Cela associe efficacement juste la méthode AuthorizeCore avec la réponse en cache. Lorsque le module de cache de sortie détecte une correspondance, il réexécute la méthode AuthorizeCore pour s'assurer que l'utilisateur actuel est autorisé à voir la réponse mise en cache. Si AuthorizeCore renvoie true, il est traité comme un hit de cache (HttpValidationStatus.Valid) et la réponse est diffusée à partir du cache sans passer par le pipeline MVC. Si AuthorizeCore renvoie la valeur false, il est traité comme un cache missing (HttpValidationStatus.IgnoreThisRequest) et le pipeline MVC s'exécute comme d'habitude pour générer la réponse. En outre, étant donné qu'un délégué est formé à AuthorizeCore (capturant ainsi l'instance particulière de AuthorizeAttribute) et sauvegardé dans un cache statique, c'est pourquoi tous les types sous-classes AuthorizeAttribute doivent être thread-safe.

+1

<3 Merci. Sincerly - merci :) Tout cela fait le sens complet maintenant. BTW, j'utilisais * Reflector * pour se pencher à ce sujet. POURQUOI? La mise en cache ne fonctionnait pas lorsque j'utilisais ma propre fonction 'AuthorizeAttribute'. (Le code se trouve dans une structure REST de code MVCContrib fork-plugable), car chaque Request appelait * ces trois lignes *. Comme vous l'avez dit, le module de cache de sortie détecte une correspondance et ré-exécute la méthode AC .. .. qui est mon problème :(Pas de cookies == aucune authentification ne se souvient, donc je dois authentifier chaque demande .. et la mise en cache est réinitialisée ? EG: http://bit.ly/bJcntB –

+0

/moi souhaite qu'il peut vous appeler Levi @ MS pour discuter :) –

2

appel à AuthorizeCore validera si la demande est autorisée. Si autorisé, il met un AddValidationCallback afin de tester si la sortie mise en cache est toujours valide en fonction de la stratégie de cache. Si c'est le cas, la sortie mise en cache est envoyée au client.

En ce qui concerne les 3 lignes pour la mise en cache; Eh bien, tout d'abord, vous devriez comprendre qu'un cache de sortie doit être correct ou aussi correct que possible. Afin de mesurer son "exactitude", le système testera s'il remplit certaines conditions (par exemple, il n'a pas été modifié).

+0

Pouvez-vous expliquer ce que fait la deuxième ligne et pourquoi? Ensuite, pouvez-vous expliquer ce que le AddValidationCallback fait/est/pourquoi, etc. Ainsi est ce que vous dites, que ... si une personne ajoute l'attribut [Authorize], ce code est appelé. MAIS, si un personal ajoute aussi un attribut [OutputCache], alors les 3 lignes ci-dessus, effectuez cela. Si c'est le cas, comment? s'il vous plaît se référer à une partie du code MVC comme preuve d'une explication. –

+0

cache.SetProxyMaxAge (new TimeSpan (0L)) est une meilleure alternative pour no-cache; cela entraînera la re-validation du cache, mais cela n'empêche PAS la mise en cache. D'autre part, No-cache ne fera rien cacher du tout. –

+0

donc vous dites que la deuxième ligne arrête la sortie de la mise en cache, s'il y avait du OutputCache. Pourquoi feraient ils cela? –