2017-10-11 2 views
5

Nous avons une page avec plusieurs formulaires. Chacun a son propre @Html.AntiForgeryToken(). Sur ma machine locale tout est génial.__RequestVerificationToken n'est pas toujours créé

Nous avons déployé vers Azure (PAAS), mais le __RequestVerificationTokenn'est pas créé à chaque requête. Parfois, il est là et parfois je reçois le Le cookie anti-falsification requis n'est pas présent et rarement je reçois les jetons ne correspondent pas à l'erreur.

Je suis complètement désemparé à ce stade. Je n'arrive pas à comprendre si quelque chose ne va pas dans notre code ou dans l'environnement Azure? Pas d'ajax dans ces formes.

Nous avons ajouté la section <machineKey> à notre web.config. Pas de mise en cache Parfois, il se produit sur les nouveaux appareils de la première fois.

+0

Avez-vous déjà trouvé la réponse? –

+0

Non, nous avons dû supprimer le contrôle antiforgery (il était utilisé pour les formulaires d'intégration simples, rien de critique à ce sujet). Notre installation Azure avait deux CD logiques, donc je suppose que c'est lié à différents CDs gérant la requête et la réponse. C'est juste ma conjecture. – TamerM

+0

Je suis triste d'entendre cela, bien que je ne pense pas que cela devrait poser problème à moins que vous ayez le domaine défini dans l'action de formulaire (qui redirigera alors l'utilisateur vers un autre CD pour le POST, mais je doute que ce serait le cas puisque si vous utilisiez l'UrlHelper, cela ne redirige pas les utilisateurs entre les domaines). –

Répondre

1

Je crois que votre problème vient d'avoir plusieurs formulaires avec différents jetons anti-falsification sur une page. Lorsque la page est demandée, vous obtenez deux jetons différents dans les champs masqués mais seulement un jeton dans les cookies. Le formulaire POST contient des jetons non concordants qui provoquent une erreur. Essayez comment AFT fonctionnera pour vous si la page ne contient qu'un seul formulaire. Si cela fonctionne bien alors mon hypothèse est correcte.

This answer contient une solution possible pour la page avec plusieurs formulaires, mais il a quelques inconvénients de sécurité comme expliqué here.

Je ne sais pas pourquoi tout fonctionne correctement sur votre localhost. J'ai créé une application simple et j'ai essayé le formulaire POST avec un jeton de cookies correct mais un ancien jeton de formulaire de la session précédente. À ma grande surprise, un tel POST passe avec succès. Peut être asp.net a un traitement spécial pour les demandes locales dans ce cas. Je n'ai trouvé aucune information à ce sujet.

Si ma réponse ne fonctionne toujours, vous pouvez vous aider à ne pas fournir des données suivantes s'il vous plaît pour une analyse plus approfondie:

  1. demande de page originale avec en-têtes HTTP retournées et former des jetons anti-contrefaçon.
  2. Formulaire Demande POST avec en-têtes HTTP envoyés.
+0

Basé sur le post de l'OP, le problème n'est pas une discordance de jetons (btw si vous avez plusieurs jetons), et ne semble pas non plus être un problème toujours présent. En outre, ASP.NET déchiffre les jetons anti-falsification avant la comparaison. Peu importe si vous avez 2 jetons différents dans un formulaire s'ils contiennent tous les deux des données correspondant au cookie. En outre, je vois dans mon propre système que plusieurs formulaires et jetons de formulaire ne sont pas le problème, le problème est qu'il n'y a aucun cookie envoyé par le navigateur du tout. –

+0

Il est vrai que les jetons ne sont pas simplement comparés en tant que tampons binaires, mais sont décryptés et comparés par jeton de sécurité conservé à l'intérieur. Bon article sur les internes de jetons anti-contrefaçon: https://www.codeproject.com/Articles/793384/ASP-NET-Anti-Forgery-Tokens-internals. OP a mentionné que, parfois, les «jetons ne correspondent pas aux erreurs», mon hypothèse pourrait donc poser problème. Si non, alors les informations que j'ai demandées au bas de ma réponse devraient clarifier au moins s'il s'agit d'un problème de client local ou de serveur distant. – CodeFuller

0

Après avoir passé une quantité importante de temps à l'enquête, en utilisant une combinaison de journaux de serveur Web Sentry et Azure, j'ai trouvé 2 principales causes des erreurs mentionnées:

1) Sur les téléphones mobiles, quand le navigateur est en arrière-plan, il peut être brusquement arrêté par le système d'exploitation pour libérer des ressources. Lorsque cela se produit, généralement, la page est stockée sur le lecteur du téléphone et rechargée à partir de là une fois le navigateur rouvert. Cependant, le problème est que le jeton Anti-Forgery, qui est un cookie de session, a déjà expiré, car il s'agit essentiellement d'une nouvelle session. Ainsi, la page se charge sans un anti-falsification de cookies, en utilisant le code HTML de la session précédente. Cela provoque l'exception The required anti-forgery cookie is not present.

2) Bien qu'apparemment apparentée, l'exception tokens do not match n'est généralement liée que de manière tangentielle. La cause semble être le comportement de l'utilisateur d'ouvrir plusieurs onglets en même temps.Le cookie anti-falsification n'est attribué que lorsqu'un utilisateur arrive sur une page contenant un formulaire. Cela signifie qu'ils peuvent aller à votre page d'accueil, et n'ont pas de cookie anti-falsification. Ensuite, ils peuvent ouvrir plusieurs onglets en utilisant le clic du milieu. Les multiples onglets sont des requêtes parallèles multiples, chacune sans cookie anti-falsification. Comme ces requêtes n'ont pas de cookie anti-falsification, pour chacune d'elles, ASP.NET génère un jeton pseudo-aléatoire distinct pour leur cookie, et l'utilise dans le formulaire; cependant, seul le résultat du dernier en-tête reçu sera conservé. Cela signifie que toutes les autres pages auront des jetons invalides sur la page, puisque leur cookie anti-falsification a été remplacé.

Pour une solution, j'ai créé un filtre global qui devrait veiller à ce que

  1. Le cookie Anti-Contrefaçon est attribué sur une page, même si la page n'a pas de forme, et
  2. Anti -Le cookie Forgery n'est pas lié à une session. Sa durée de vie devrait être ajustée pour correspondre au jeton de connexion de l'utilisateur, mais elle devrait persister entre les sessions au cas où un appareil mobile rechargerait la page sans la session.

Le code ci-dessous est un FilterAttribute qui doit être ajouté à l'intérieur de FilterConfig.cs en tant que filtre global. Veuillez noter que, bien que je ne crois pas que cela créerait un trou de sécurité, je ne suis en aucun cas un expert en sécurité, donc toute contribution est la bienvenue.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] 
public class AntiForgeryFilter : FilterAttribute, IActionFilter 
{ 
    public void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var cookie = filterContext.HttpContext.Request.Cookies.Get(AntiForgeryConfig.CookieName); 
     var addCookie = true; 
     if (string.IsNullOrEmpty(cookie?.Value)) 
     { 
      cookie = filterContext.HttpContext.Response.Cookies.Get(AntiForgeryConfig.CookieName); 
      addCookie = false; 
     } 
     if (string.IsNullOrEmpty(cookie?.Value)) 
     { 
      AntiForgery.GetTokens(null, out string cookieToken, out string _); 
      cookie = new HttpCookie(AntiForgeryConfig.CookieName, cookieToken) 
      { 
       HttpOnly = true, 
       Secure = AntiForgeryConfig.RequireSsl 
      }; 
     } 
     cookie.Expires = DateTime.UtcNow.AddYears(1); 
     if(addCookie) filterContext.HttpContext.Response.Cookies.Add(cookie); 
    } 

    public void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
    } 
}