inclure anti-forgerytoken dans ajax post ASP.NET MVC

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

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) {
            ...
        }
    });

quand je supprime l'attribut [ValidateAntiForgeryToken] juste pour voir si les données (avec le token) sont passées comme paramètres au contrôleur, je peux voir qu'elles sont passées. Mais pour une raison quelconque, le Le message A required anti-forgery token was not supplied or was invalid. apparaît quand j'ai remis l'attribut en place.

des idées?

MODIFIER

l'anti-forgerytoken est généré à l'intérieur d'un formulaire, mais je n'utilise pas une action Soumettre pour le soumettre. Au lieu de cela, je suis juste obtenir la valeur du jeton en utilisant jquery et ensuite essayer d'ajax poster cela.

voici le formulaire qui contient le jeton, et se trouve à la page principale:

<form id="__AjaxAntiForgeryForm" action="#" method="post">
    @Html.AntiForgeryToken()
</form>
122
demandé sur Community 2013-01-23 10:18:36

9 réponses

vous avez incorrectement spécifié le contentType à application/json .

Voici un exemple de comment cela fonctionne.

contrôleur:

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

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

:

@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>
223
répondu Darin Dimitrov 2013-01-23 06:54:03

l'Autre (moins javascriptish) approche, que j'ai fait, va quelque chose comme ceci:

tout d'Abord, un helper 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 de caractères

__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"

si nous pouvons l'utiliser comme ceci

$(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!

51
répondu Max Wikström 2013-04-17 10:23:28

c'est si simple! lorsque vous utilisez @Html.AntiForgeryToken() dans votre code html cela signifie que le serveur a signé cette page et chaque requête envoyée au serveur à partir de cette page particulière a un signe qui est empêché d'envoyer une fausse requête par les pirates. ainsi, pour que cette page soit authentifiée par le serveur, vous devez passer par deux étapes:

1.envoyer un paramètre nommé __RequestVerificationToken et pour obtenir sa valeur utiliser 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 Il suffit de décorer votre méthode d'action par [ValidateAntiForgeryToken]

32
répondu Abolfazl 2016-04-16 15:35:39


        function DeletePersonel(id) {

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

                $.ajax({
                    type: 'POST',
                    url: '/Personel/Delete/' + id,
                    data: data,
                    cache: false,
                    processData: false,
                    contentType: false,
                    success: function (result) {

                    }
                });

        }
    

        public static class HtmlHelper
        {
            public static string GetAntiForgeryToken()
            {
                System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match(System.Web.Helpers.AntiForgery.GetHtml().ToString(), "(?:value=\")(.*)(?:\")");
                if (value.Success)
                {
                    return value.Groups[1].Value;
                }
                return "";
            }
        }
4
répondu ismail eski 2016-09-01 18:41:46

je sais que c'est une vieille question. Mais je vais ajouter ma réponse de toute façon, pourrait aider quelqu'un comme moi.

si vous ne voulez pas traiter le résultat de l'action post du contrôleur, comme appeler la méthode LoggOff de Accounts contrôleur, vous pouvez faire comme 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
répondu Aamir 2015-06-27 21:22:40

j'ai essayé beaucoup d'exercices et aucun d'eux n'a travaillé pour moi. L'exception était "le champ de formulaire anti-contrefaçon requis "_ _ _ RequestVerificationToken".

ce qui m'a aidé était de changer de forme .l'ajax .post:

$.post(
    url,
    $(formId).serialize(),
    function (data) {
        $(formId).html(data);
    });
0
répondu Stefan Michev 2016-07-19 15:06:19

In Asp.Net MVC lorsque vous utilisez @Html.AntiForgeryToken() Razor crée un champ d'entrée caché avec le nom __RequestVerificationToken pour stocker des jetons. Si vous voulez écrire une implémentation AJAX, vous devez récupérer ce token vous-même et le passer comme paramètre au serveur pour qu'il puisse être validé.

Étape 1: Obtenir le jeton

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

Étape 2: Passer le jeton dans 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 contenu le type 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 de l'essayer.

https://github.com/lambda2016/AjaxValidateAntiForgeryToken

0
répondu Frank Odoom 2016-07-20 19:16:49

utilisez 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
répondu Komal Narang 2018-09-19 16:36:41

In Asp.Net vous pouvez demander le token directement, comme documenté :

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

et l'utiliser 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());
})
0
répondu Ruard van Elburg 2018-10-04 15:44:07