Connexion de validation de la demande de jeton de problème

j'ai parcouru les journaux d'erreurs d'un projet de développement et j'ai trouvé l'erreur suivante (Nom changé pour protéger le coupable innocent) -

le jeton anti-contrefaçon fourni était destiné à l'utilisateur"", mais le courant l'utilisateur est"administrateur".

Ce n'était pas particulièrement difficile à reproduire-

  1. ouvrir la demande à la page de connexion
  2. ouvrir une deuxième fenêtre ou onglet dans le même navigateur sur le même ordinateur à la page de connexion avant de se connecter dans
  3. Se Connecter dans la première fenêtre (ou en effet la deuxième, l'ordre n'a pas d'importance)
  4. tentative de connexion dans la fenêtre de connexion restante

la trace de La pile, c'est

Système.Web.Mvc.HttpAntiForgeryException (0x80004005): le anti-faux jeton a été conçu pour l'utilisateur "", mais l'utilisateur actuel est "admin." à Système.Web.Helper.AntiXsrf.TokenValidator.ValidateTokens(HttpContextBase httpContext, l'Identité de l'identité, AntiForgeryToken sessionToken, AntiForgeryToken fieldToken) à Système.Web.Helper.AntiXsrf.AntiForgeryWorker.Valider(HttpContextBase httpContext) au système.Web.Helper.AntiForgery.Valider() à Système.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization(AuthorizationContext) filterContext) à Système.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters (Controllercontentext controllerContext, IList ' 1 filtres, ActionDescriptor actionDescriptor) à Système.Web.Mvc.Asynchrone.AsyncControllerActionInvoker. C__DisplayClass25.b _ _ 1e(AsyncCallback) asyncCallback, Object asyncState)

la signature de la méthode login est -

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
...
}

c'est exactement la même chose que la signature pour la méthode dans un internet "ASP.NET MVC 4 Web Application" templated project, qui indique que Microsoft soit a estimé que la Validatetiforgerytoken était nécessaire / meilleure pratique, ou simplement a ajouté l'attribut ici parce qu'il a été utilisé partout ailleurs.

évidemment il n'y a rien que je puisse faire pour gérer le problème dans cette méthode comme il n'est pas atteint, le Validatetiforgerytoken est un filtre pré-requête qui bloque la requête avant qu'elle n'atteigne le contrôleur.

je pourrais vérifier si L'utilisateur est authentifié via Ajax avant de soumettre le formulaire et tenter de rediriger vers eux si oui, ou tout simplement supprimer l'attribut.

la question Est la suivante - je comprends que le token est conçu pour empêcher les requêtes d'un autre site (CSRF) lorsque l'utilisateur est déjà authentifié contre votre site donc sur cette base est-ce une question de le supprimer d'un formulaire qui, par définition, sera utilisé par les utilisateurs non authentifiés ?

probablement l'attribut dans ce cas est conçu pour atténuer les acteurs malveillants fournissant de faux formulaires de connexion pour votre application (bien que d'ici le moment où l'exception est jetée présumément l'Utilisateur a déjà entré ses détails qui auront été enregistrés - mais il pourrait les alerter quelque chose ne va pas). Sinon, soumettre des justificatifs d'identité incorrects au formulaire à partir d'un site externe aura exactement le même résultat que sur le site lui-même sûrement? Je ne compte pas sur la validation et l'hygiène du client pour nettoyer les entrées potentiellement dangereuses.

Ont d'autres devs rencontré ce problème (ou ne nous ont exceptionnellement les utilisateurs créatifs) et si oui, comment avez-vous résolu/atténués?

mise à Jour: Ce problème existe toujours dans MVC5, entièrement intentionnellement, maintenant avec le message d'erreur " le jeton anti-contrefaçon fourni était destiné à un utilisateur basé sur des revendications différent que l'utilisateur actuel."lors de l'utilisation du modèle par défaut et des fournisseurs D'identité. Il y a une question pertinente et une réponse intéressante de la part du développeur de Microsoft Evangelist et du collaborateur de Troy, L'auteur de PluralSight Adam Tuliper à jeton anti-contrefaçon sur la page de connexion qui recommande simplement de supprimer le jeton.

65
demandé sur Community 2013-09-30 18:25:44

4 réponses

je viens de tester ce modèle sur ASafaWeb avec le même résultat (il utilise la même implémentation par défaut). Voici ce que je crois qui se passe

  1. les deux formulaires de connexion se chargent avec le même cookie __RequestVerificationToken (c'est juste le même ensemble dans le même DOM) et le même champ caché __ _ RequestVerificationToken. Ces jetons sont transmis à un utilisateur anonyme.
  2. formulaire de Connexion à l'Un des postes ci-dessus jetons, valide, puis renvoie un auth cookie, qui est maintenant dans le navigateur DOM
  3. les messages de formulaire B de connexion aussi avec les tokens ci-dessus mais maintenant, il est également l'affichage avec le cookie d'auth ensemble du formulaire de connexion A ainsi.

le problème est que le token n'est pas valide à l'étape 3 parce qu'il est saisi par un utilisateur anonyme mais il est passé dans la demande par un utilisateur authentifié. C'est pourquoi vous voyez l'erreur: le jeton anti-contrefaçon fourni était destiné à l'utilisateur "", mais l'utilisateur actuel est "admin "

vous avez seulement ce problème parce que le formulaire b a été chargé avant que le formulaire A soit posté donc le formulaire b s'attend à être posté par un utilisateur anonyme.

est-ce une question de le supprimer d'un formulaire qui, par définition, sera utilisé par des utilisateurs non authentifiés?

le risque sous-jacent prédominant que les jetons anti-contrefaçon protègent contre est CSRF qui habituellement tire avantage des utilisateurs authentifiés en raison du fait que toute demande de leur navigateur peut être trompée dans l'émission sera automatiquement accompagnée d'un cookie d'auth donc l'action sera effectuée en leur nom. Ce risque n'existe pas sur le formulaire de connexion car habituellement l'utilisateur n'est pas authentifié et le pire cas CSRF ici est que login est contrefait et puis échoue; vous n'êtes pas exactement transférer de l'argent au nom de l'utilisateur!

il y a d'autres avantages au jeton anti-contrefaçon cependant: par exemple, il empêche les attaques par la force brute exécutant réellement la méthode et frappant le DB. Vous devez décider si vous êtes moins inquiet à ce sujet et plus inquiet du scénario que vous rencontrez dans votre question. Soit ça, soit vous devez vous déposer quelque part dans le pipeline de demande et prendre des mesures si un le cookie auth est déjà présent dans la requête avant la validation anti-contrefaçon.

franchement cependant, je ne suis pas sûr de voir le problème; pour reproduire ce problème, l'utilisateur doit avoir plusieurs formulaires de connexion ouverts en même temps et puis essayer de se connecter à chacun dans la succession - est-ce que cela va vraiment se produire assez de s'inquiéter? Et quand cela arrive, est-ce vraiment important que le deuxième login renvoie une page d'erreur personnalisée (ce que vous feriez bien sûr dans la production)? À mon humble avis, laissez le comportement par défaut.

59
répondu Troy Hunt 2013-10-01 07:29:15

le code de validation qui s'exécute contre un anti – Forgerytoken vérifie également que les informations d'identification de l'utilisateur n'ont pas changé-elles sont également cryptées dans le cookie. Cela signifie que si vous vous êtes connecté ou déconnecté dans un popup ou un autre onglet de navigateur, votre soumission de formulaire échouera avec l'exception suivante:

System.Web.Mvc.HttpAntiForgeryException (0x80004005):
The provided anti-forgery token was meant for user "", but the current user is "SomeOne".

vous pouvez éteindre ceci en mettant AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start "151960920 méthode" de l'intérieur Global.fichier asax .

quand un anti-Forgerytoken ne valide pas votre site va jeter une Exception de type système.Web.Mvc.HttpAntiForgeryException . Vous pouvez rendre cela un peu plus facile en donnant au moins à l'utilisateur une page plus informative ciblée sur ces exceptions en attrapant le HttpAntiForgeryException .

private void Application_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();

if (ex is HttpAntiForgeryException)
  {
    Response.Clear();
    Server.ClearError(); //make sure you log the exception first
    Response.Redirect("/error/antiforgery", true);
  }
}
12
répondu Zia Ul Mustafa 2015-09-17 07:31:17

d'accord, corrigez-moi si mon hypothèse est incorrecte.

lorsque cette exception est lancée, vous préférez laisser l'utilisateur continuer tout en affichant peut-être un message/Avertissement pertinent? Parce que lorsque cette exception est lancée, nous pouvons déjà savoir si l'utilisateur actuel est authentifié--nous avons accès à la requête.

alors, pourquoi ça ne serait pas acceptable?

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
...
}

/// <summary>
/// Handle HttpAntiForgeryException and redirect if user is already authenticated
/// </summary>
/// <param name="filterContext"></param>
/// <remarks>
/// See: /q/login-request-validation-token-issue-75804/"action"] as string;
    var controller = filterContext.RequestContext.RouteData.Values["controller"] as string;

    if ((filterContext.Exception is HttpAntiForgeryException) &&
        action == "Login" &&
        controller == "MyController" &&
        filterContext.RequestContext.HttpContext.User != null &&
        filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
    {
        LogManager.GetCurrentClassLogger().Warn(
            "Handled AntiForgery exception because user is already Authenticated: " +
                filterContext.Exception.Message, filterContext.Exception);

        filterContext.ExceptionHandled = true;

        // redirect/show error/whatever?
        filterContext.Result = new RedirectResult("/warning");
    }
}

est - ce que je manque quelque chose d'évident ici? Je retirerai cette réponse si elle implique quelque chose que je ne vois pas.

9
répondu kamranicus 2015-06-02 15:48:39

j'ai eu le même problème, je l'ai résolu en ajoutant machineKey à système.web >

<machineKey validationKey="your machine key numbers" 
decryptionKey="Your description key nuumbers" validation="SHA1" decryption="AES" />

voici un site qui génère des clés Machnie uniques http://www.developerfusion.com/tools/generatemachinekey /

fonctionne très bien, je comprends que la contrefaçon Anti peut ne pas être nécessaire dans une page de connexion, mais si quelqu'un est déterminé à pirater votre site, il réconfortant de savoir que [ValidateAntiForgeryToken] est là pour les contrecarrer hors.

-4
répondu MVCdragon 2014-02-15 07:27:49