web-dev-qa-db-fra.com

Le cookie anti-contrefaçon requis "__RequestVerificationToken" n'est pas présent

Mon site Web lève cette exception environ 20 fois par jour, généralement le formulaire fonctionne bien, mais il y a des cas où ce problème se produit et je ne sais pas pourquoi est si aléatoire.

Ceci est enregistré exception par elmah

500 HttpAntiForgery Le cookie anti-contrefaçon requis __RequestVerificationToken "n'est pas présent.

Mais la forme qu'il envoie le jeton comme indiqué sur le journal XML par elmah

<form>
    <item name="__RequestVerificationToken">
      <value string="DNbDMrzHmy37GPS6IFH-EmcIh4fJ2laezIrIEev5f4vOhsY9T7SkH9-1b7GPjm92CTFtb4dGqSe2SSYrlWSNEQG1MUlNyiLP1wtYli8bIh41"/>
    </item>
    <item name="toPhone">
      <value string="XXXXXX"/>
    </item>
    <item name="smsMessage">
      <value string="xxxxxxxx"/>
    </item>
</form>

Ceci est ma méthode sur le contrôleur qui utilise l'attribut de données pour vérifier si le jeton est valide ou non

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Send(SMSModel model)
{
    // my code goes here
}

Ceci est ma forme sur la vue

@using (Html.BeginForm("Send", "SMS", FormMethod.Post, new { @class = "form-sms", autocomplete = "off" }))
{
    @Html.AntiForgeryToken()
    <div class="row">
        <div class="col-md-12">
            <div class="form-group">
                <div class="input-group">
                    <div class="input-group-addon">+53</div>
                    @Html.TextBoxFor(m => m.toPhone, new { @class = "form-control", placeholder = "teléfono", required = "required", type = "tel", maxlength = 8 })
                </div>
            </div>
        </div>
    </div>
    <div class="form-group" style="position:relative">
        <label class="sr-only" for="exampleInputEmail3">Message (up to 135 characters)</label>
        @Html.TextAreaFor(m => m.smsMessage, new { rows = 4, @class = "form-control", placeholder = "escriba aquí su mensaje", required = "required", maxlength = "135" })
        <span class="char-count">135</span>
    </div>
    if (ViewBag.Sent == true)
    {
        <div class="alert alert-success alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <strong>Su mensaje ha sido enviado <span class="hidden-xs">satisfactoriamente</span></strong>
        </div>
    }
    if (ViewBag.Error == true)
    {
        <div class="alert alert-danger alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <strong>Error:</strong> Por favor revise el número de teléfono.
        </div>
    }
    <div class="errorToMany"></div>
    <button type="submit" class="btn btn-default btn-block">Enviar SMS</button>
}

Et voici comment je publie mes données en utilisant AJAX

$('form.form-sms').submit(function (event) {
    $.ajax({
        url: $(this).attr("action"),
        type: "POST",
        data: $(this).serializeArray(),
        beforeSend: function (xhr) {
            $('.btn-default').attr("disabled", true);
            $('.btn-default').html("Enviando...")
        },
        success: function (data, textStatus, jqXHR) {
            if (data[0] == false && data[1] == "1") {
               some code 
            } else {
               location.reload();
            }
        },
        error: function (jqXHR, textStatus, errorThrown) { }
    });
    return false;
});

Le formulaire fonctionne bien la plupart du temps mais cette erreur continue de se produire et je ne sais pas pourquoi, j'ai vérifié d'autres questions ici sur Stack Overflow mais rien ne fonctionne pour moi.

Pour plus d'explications sur la façon dont je publie les données.

Ce formulaire pour envoyer SMS a les champs ToNumber et Message. Lorsqu'un utilisateur clique sur le bouton d'envoi, la fonction AJAX prend le contrôle et la publie en sérialisant le champ du formulaire) données, lorsque ma fonction dans le contrôleur se termine et renvoie le résultat JSON indiquant que tout s'est bien passé, la méthode AJAX recharge la page affichant un message de réussite à l'utilisateur.

Toutes les idées qui pourraient être à l'origine de ce problème.

23
General Electric

Il semble presque que les choses fonctionnent comme prévu.

La façon dont fonctionne l'anti contrefaçon @Html.AntiForgeryToken() consiste à injecter un champ de formulaire caché nommé __RequestVerificationToken dans la page ET il place également un cookie dans le navigateur.

Lorsque le formulaire est renvoyé, les deux sont comparés et s'ils ne correspondent pas ou si le cookie est manquant, l'erreur est renvoyée.

Peu importe qu'Elmah enregistre que le formulaire envoie __RequestVerificationToken. Il le sera toujours, même en cas d'attaque CSRF, car il s'agit simplement du champ de formulaire caché.

<input name="__RequestVerificationToken" type="hidden" value="DNbDMrzHmy37GPS6IFH-EmcIh4fJ2laezIrIEev5f4vOhsY9T7SkH9-1b7GPjm92CTFtb4dGqSe2SSYrlWSNEQG1MUlNyiLP1wtYli8bIh41" />

Le message d'erreur indique en revanche que le COOKIE correspondant n'est pas envoyé:

500 HttpAntiForgery Le cookie anti-contrefaçon requis __RequestVerificationToken "n'est pas présent.

Donc, fondamentalement, quelqu'un/quelque chose rejoue le post de formulaire sans faire la demande d'origine pour obtenir le cookie. En tant que tels, ils ont le champ de formulaire masqué __RequestVerificationToken mais PAS le cookie pour le vérifier.

Il semble donc que les choses fonctionnent comme elles le devraient. Vérifiez vos journaux concernant les numéros IP et les référents, etc. Vous pouvez être attaqué ou faire quelque chose de bizarre ou de bogué lors de la redirection du contenu de votre formulaire. Comme ci-dessus, referrers est un bon point de départ pour ce type d'erreur, en supposant que cela ne soit pas usurpé.

Notez également que selon MDN

location.reload();

La méthode Location.reload () recharge la ressource à partir de l'URL actuelle. Son paramètre unique facultatif est un booléen qui, lorsqu'il est vrai, entraîne le rechargement de la page depuis le serveur. S'il est faux ou non spécifié, le navigateur peut recharger la page depuis son cache .

Si c'est le cas, à l'occasion de chargement à partir du cache, vous pourriez vous retrouver avec un POST qui a l'ancien jeton de page mais pas le cookie.

Alors essayez:

location.reload(true);
21
rism

Ran dans un problème similaire récemment. Le cookie anti-contrefaçon manquait en effet, donc (comme d'autres l'ont souligné) soit

  1. le serveur n'a pas ajouté le cookie à demander, ou
  2. le navigateur l'a rejeté.

Dans mon cas, c'était le serveur: je n'utilisais pas SSL sur l'environnement local, mais dans web.config J'avais la ligne suivante:

<httpCookies requireSSL="True"/>

La solution dans ce cas consiste à basculer vers SSL ou à conserver la valeur définie sur "False" pour l'environnement local.

12
Rod Borchevskyi

En plus de l'excellente réponse de rism, une autre raison possible de rencontrer cette erreur est parce que votre navigateur ou plugin de navigateur empêche les cookies d'être définis.

8
Samuel Liew

J'ai eu le même problème dans le navigateur Edge.

J'ai résolu ce problème en modifiant les paramètres du navigateur.

Suivez les instructions pour résoudre le problème:

Accédez à Paramètres> Afficher les paramètres avancés> Cookies> Passer à "Ne pas bloquer les cookies".

Fermez le navigateur et vérifiez.

J'ai pensé que cela pourrait aider quelqu'un.

3
Rajeev Kumar

vérifiez si vous manquez cette ligne dans votre front-end @ Html.AntiForgeryToken () ou non

1

Pourrait vouloir jeter un oeil à cette question. Le jeton de cookie anti-falsification et le jeton de champ de formulaire ne correspondent pas dans MVC 4

Il est possible que ce soit un problème de délai d'attente. Fondamentalement, lorsque le délai d'expiration se produit, le cookie n'est pas stocké car l'utilisateur iis sous lequel le site est exécuté n'a pas l'accès approprié. Pour moi, j'ai changé le pool d'applications pour charger le profil utilisateur et cela a semblé le corriger.