web-dev-qa-db-fra.com

inclure antiforgerytoken dans ajax post ASP.NET MVC

J'ai des problèmes avec l'AntiForgeryToken avec ajax. J'utilise ASP.NET MVC 3. J'ai essayé la solution dans les appels jQuery Ajax et le Html.AntiForgeryToken () . En utilisant cette solution, le jeton est maintenant transmis:

var data = { ... } // with token, key is '__RequestVerificationToken'

$.ajax({
        type: "POST",
        data: data,
        datatype: "json",
        traditional: true,
        contentType: "application/json; charset=utf-8",
        url: myURL,
        success: function (response) {
            ...
        },
        error: function (response) {
            ...
        }
    });

Lorsque je supprime l'attribut [ValidateAntiForgeryToken] uniquement pour voir si les données (avec le jeton) sont transmises en tant que paramètres au contrôleur, je peux voir qu'elles sont en cours de transmission. Mais pour une raison quelconque, le message A required anti-forgery token was not supplied or was invalid. s'affiche quand je remets l'attribut.

Des idées?

MODIFIER

L'antiforgerytoken est généré dans un formulaire, mais je n'utilise pas d'action de soumission pour le soumettre. Au lieu de cela, j'obtiens simplement la valeur du jeton à l'aide de jQuery, puis j'essaie d'ajaxer cela.

Voici le formulaire contenant le jeton, situé dans la page maître supérieure:

<form id="__AjaxAntiForgeryForm" action="#" method="post">
    @Html.AntiForgeryToken()
</form>
129
OJ Raqueño

Vous avez incorrectement spécifié la contentType à application/json

Voici un exemple de la façon dont cela pourrait fonctionner.

Manette:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(string someValue)
    {
        return Json(new { someValue = someValue });
    }
}

Vue:

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
    @Html.AntiForgeryToken()
}

<div id="myDiv" data-url="@Url.Action("Index", "Home")">
    Click me to send an AJAX request to a controller action
    decorated with the [ValidateAntiForgeryToken] attribute
</div>

<script type="text/javascript">
    $('#myDiv').submit(function () {
        var form = $('#__AjaxAntiForgeryForm');
        var token = $('input[name="__RequestVerificationToken"]', form).val();
        $.ajax({
            url: $(this).data('url'),
            type: 'POST',
            data: { 
                __RequestVerificationToken: token, 
                someValue: 'some value' 
            },
            success: function (result) {
                alert(result.someValue);
            }
        });
        return false;
    });
</script>
235
Darin Dimitrov

Une autre approche (moins de javascript), que j'ai faite, ressemble à ceci:

Tout d'abord, un assistant HTML

public static MvcHtmlString AntiForgeryTokenForAjaxPost(this HtmlHelper helper)
{
    var antiForgeryInputTag = helper.AntiForgeryToken().ToString();
    // Above gets the following: <input name="__RequestVerificationToken" type="hidden" value="PnQE7R0MIBBAzC7SqtVvwrJpGbRvPgzWHo5dSyoSaZoabRjf9pCyzjujYBU_qKDJmwIOiPRDwBV1TNVdXFVgzAvN9_l2yt9-nf4Owif0qIDz7WRAmydVPIm6_pmJAI--wvvFQO7g0VvoFArFtAR2v6Ch1wmXCZ89v0-lNOGZLZc1" />
    var removedStart = antiForgeryInputTag.Replace(@"<input name=""__RequestVerificationToken"" type=""hidden"" value=""", "");
    var tokenValue = removedStart.Replace(@""" />", "");
    if (antiForgeryInputTag == removedStart || removedStart == tokenValue)
        throw new InvalidOperationException("Oops! The Html.AntiForgeryToken() method seems to return something I did not expect.");
    return new MvcHtmlString(string.Format(@"{0}:""{1}""", "__RequestVerificationToken", tokenValue));
}

qui retournera une chaîne

__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"

afin que nous puissions l'utiliser comme ça

$(function () {
    $("#submit-list").click(function () {
        $.ajax({
            url: '@Url.Action("SortDataSourceLibraries")',
            data: { items: $(".sortable").sortable('toArray'), @Html.AntiForgeryTokenForAjaxPost() },
            type: 'post',
            traditional: true
        });
    });
});

Et ça a l'air de marcher!

55
Max Wikstrom

c'est si simple! lorsque vous utilisez @Html.AntiForgeryToken() dans votre code html, cela signifie que le serveur a signé cette page et que chaque demande envoyée au serveur à partir de cette page particulière a un signe qui empêche d'empêcher l'envoi d'une fausse demande par des pirates. Pour que cette page soit authentifiée par le serveur, vous devez suivre deux étapes:

1.envoyez un paramètre nommé __RequestVerificationToken et pour obtenir sa valeur, utilisez les codes ci-dessous:

<script type="text/javascript">
    function gettoken() {
        var token = '@Html.AntiForgeryToken()';
        token = $(token).val();
        return token;
   }
</script>

par exemple prendre un appel ajax

$.ajax({
    type: "POST",
    url: "/Account/Login",
    data: {
        __RequestVerificationToken: gettoken(),
        uname: uname,
        pass: pass
    },
    dataType: 'json',
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',
    success: successFu,
});

et étape 2, décorez simplement votre méthode d'action avec [ValidateAntiForgeryToken]

35
Abolfazl


 function DeletePersonel (id) {

 var data = new FormData (); 
 data.append ("__ RequestVerificationToken", "@ HtmlHelper.GetAntiForgeryToken ()"); 

 $ .ajax ({
 type: 'POST', 
 url: '/ Personel/Delete /' + id, 
 données: données, 
 cache: false, 
 processData: false, 
 contentType: false, 
 success: function (résultat) {

} 
}); 

 } 
 

 Classe statique publique HtmlHelper 
 {
 chaîne publique statique GetAntiForgeryToken () 
 {
 System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match (System.Web.Helpers.AntiForgery.GetHtml (). ToString (), "(?: Value = \") (.:). :\")"); 
 si (valeur.Succès) 
 {
 valeur de retour.Groupes [1] .Value; 
 } 
 revenir "";
 } 
 } 
5
ismail eski

Dans Asp.Net Core, vous pouvez demander le jeton directement, comme documenté :

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf    
@functions{
    public string GetAntiXsrfRequestToken()
    {
        return Xsrf.GetAndStoreTokens(Context).RequestToken;
    }
}

Et utilisez-le en javascript:

function DoSomething(id) {
    $.post("/something/todo/"+id,
               { "__RequestVerificationToken": '@GetAntiXsrfRequestToken()' });
}

Vous pouvez ajouter le filtre global recommandé, comme documenté :

services.AddMvc(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
4
Ruard van Elburg

Dans Asp.Net MVC, lorsque vous utilisez @Html.AntiForgeryToken(), Razor crée un champ de saisie masqué avec le nom __RequestVerificationToken pour stocker les jetons. Si vous voulez écrire une implémentation AJAX, vous devez aller chercher ce jeton vous-même et le transmettre en tant que paramètre au serveur pour qu'il puisse être validé.

Étape 1: récupérez le jeton

var token = $('input[name="`__RequestVerificationToken`"]').val();

Étape 2: transmettez le jeton à l'appel AJAX

function registerStudent() {

var student = {     
    "FirstName": $('#fName').val(),
    "LastName": $('#lName').val(),
    "Email": $('#email').val(),
    "Phone": $('#phone').val(),
};

$.ajax({
    url: '/Student/RegisterStudent',
    type: 'POST',
    data: { 
     __RequestVerificationToken:token,
     student: student,
        },
    dataType: 'JSON',
    contentType:'application/x-www-form-urlencoded; charset=utf-8',
    success: function (response) {
        if (response.result == "Success") {
            alert('Student Registered Succesfully!')

        }
    },
    error: function (x,h,r) {
        alert('Something went wrong')
      }
})
};

Note: le type de contenu doit être 'application/x-www-form-urlencoded; charset=utf-8'

J'ai téléchargé le projet sur Github; vous pouvez le télécharger et l'essayer.

https://github.com/lambda2016/AjaxValidateAntiForgeryToken

2
Frank Odoom

Je sais que c'est une vieille question. Mais je vais quand même ajouter ma réponse, cela pourrait aider quelqu'un comme moi. 

Si vous ne voulez pas traiter le résultat de l'action post du contrôleur, comme en appelant la méthode LoggOff du contrôleur Accounts, vous pouvez utiliser la version suivante de la réponse de @DarinDimitrov:

@using (Html.BeginForm("LoggOff", "Accounts", FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
    @Html.AntiForgeryToken()
}

<!-- this could be a button -->
<a href="#" id="ajaxSubmit">Submit</a>

<script type="text/javascript">
    $('#ajaxSubmit').click(function () {

        $('#__AjaxAntiForgeryForm').submit();

        return false;
    });
</script>
2
Aamir

J'ai essayé beaucoup de solutions de contournement et aucune d'entre elles n'a fonctionné pour moi. L'exception était "Le champ de formulaire anti-falsification requis" __RequestVerificationToken ". 

Ce qui m’a aidé, c’est de passer de .ajax à .post: 

$.post(
    url,
    $(formId).serialize(),
    function (data) {
        $(formId).html(data);
    });
0
Stefan Michev

Le jeton ne fonctionnera pas s'il a été fourni par un autre contrôleur. Par exemple. cela ne fonctionnera pas si la vue a été renvoyée par le contrôleur Accounts, mais vous POST au contrôleur Clients.

0
OutstandingBill

Dans le contrôleur de compte:

    // POST: /Account/SendVerificationCodeSMS
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public JsonResult SendVerificationCodeSMS(string PhoneNumber)
    {
        return Json(PhoneNumber);
    }

En vue:

$.ajax(
{
    url: "/Account/SendVerificationCodeSMS",
    method: "POST",
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',
    dataType: "json",
    data: {
        PhoneNumber: $('[name="PhoneNumber"]').val(),
        __RequestVerificationToken: $('[name="__RequestVerificationToken"]').val()
    },
    success: function (data, textStatus, jqXHR) {
        if (textStatus == "success") {
            alert(data);
            // Do something on page
        }
        else {
            // Do something on page
        }
    },
    error: function (jqXHR, textStatus, errorThrown) {
        console.log(textStatus);
        console.log(jqXHR.status);
        console.log(jqXHR.statusText);
        console.log(jqXHR.responseText);
    }
});

Il est important de définir contentType sur 'application/x-www-form-urlencoded; charset=utf-8' ou tout simplement d’omettre contentTypede l’objet ...

0
Adel Mourad

N'hésitez pas à utiliser la fonction ci-dessous:

function AjaxPostWithAntiForgeryToken(destinationUrl, successCallback) {
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;
$.ajax({
    type: "POST",
    url: destinationUrl,
    data: { __RequestVerificationToken: token }, // Your other data will go here
    dataType: "json",
    success: function (response) {
        successCallback(response);
    },
    error: function (xhr, status, error) {
       // handle failure
    }
});

}

0
Komal Narang