voeg anti-vervalsingstoken toe in ajax na ASP.NET MVC

Ik heb problemen met de AntiForgeryToken met ajax. Ik gebruik ASP.NET MVC 3. Ik heb de oplossing geprobeerd in jQuery Ajax-oproepen en de Html.AntiForgeryToken(). Met die oplossing wordt het token nu doorgegeven:

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

Als ik het kenmerk [ValidateAntiForgeryToken]verwijder om te zien of de gegevens (met het token) als parameters aan de controller worden doorgegeven, kan ik zien dat ze worden doorgegeven. Maar om de een of andere reden is het A required anti-forgery token was not supplied or was invalid.bericht verschijnt nog steeds wanneer ik het kenmerk terugplaats.

Enig idee?

BEWERKEN

Het anti-vervalsingstoken wordt gegenereerd in een formulier, maar ik gebruik geen verzendactie om het in te dienen. In plaats daarvan krijg ik gewoon de waarde van het token met behulp van jQuery en probeer ik dat vervolgens door ajax te posten.

Hier is het formulier dat het token bevat, en bevindt zich op de bovenste hoofdpagina:

<form id="__AjaxAntiForgeryForm" action="#" method="post">
    @Html.AntiForgeryToken()
</form>

Antwoord 1, autoriteit 100%

U heeft het contentTypeonjuist opgegeven voor application/json.

Hier is een voorbeeld van hoe dit zou kunnen werken.

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Index(string someValue)
    {
        return Json(new { someValue = someValue });
    }
}

Bekijken:

@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>

Antwoord 2, autoriteit 20%

Een andere(minder javascript-achtige) benadering, die ik deed, gaat ongeveer als volgt:

Eerst een Html-helper

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

die een string teruggeeft

__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"

zodat we het zo kunnen gebruiken

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

En het lijkt te werken!


Antwoord 3, autoriteit 18%

het is zo simpel! wanneer u @Html.AntiForgeryToken()in uw html-code gebruikt, betekent dit dat de server deze pagina heeft ondertekend en dat elk verzoek dat vanaf deze specifieke pagina naar de server wordt verzonden, een teken heeft dat geen nep kan verzenden verzoek van hackers. dus om deze pagina door de server te verifiëren, moet u twee stappen doorlopen:

1.stuur een parameter met de naam __RequestVerificationTokenen gebruik onderstaande codes om de waarde op te halen:

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

neem bijvoorbeeld een ajax-oproep aan

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

en stap 2 versier je actiemethode gewoon met [ValidateAntiForgeryToken]


Antwoord 4, autoriteit 4%

In Asp.Net Core kunt u de token rechtstreeks aanvragen, zoals gedocumenteerd:

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

En gebruik het in javascript:

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

U kunt het aanbevolen algemene filter toevoegen, zoals gedocumenteerd:

services.AddMvc(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})

Bijwerken

De bovenstaande oplossing werkt in scripts die deel uitmaken van de .cshtml. Als dit niet het geval is, kunt u hier niet direct gebruik van maken. Mijn oplossing was om een ​​verborgen veld te gebruiken om de waarde eerst op te slaan.

Mijn oplossing, ik gebruik nog steeds GetAntiXsrfRequestToken:

Als er geen formulier is:

<input type="hidden" id="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">

Het kenmerk namekan worden weggelaten omdat ik het kenmerk idgebruik.

Elk formulier bevat dit token. Dus in plaats van nog een andere kopie van hetzelfde token in een verborgen veld toe te voegen, kunt u ook zoeken naar een bestaand veld met name. Let op: er kunnen meerdere formulieren in een document zijn, dus nameis in dat geval niet uniek. In tegenstelling tot een idkenmerk dat uniek is.

Zoek in het script, zoek per id:

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

Een alternatief, zonder het token te hoeven referent, is het formulier in met het script.

Voorbeeldformulier:

<form id="my_form" action="/something/todo/create" method="post">
</form>

Het token wordt automatisch toegevoegd aan het formulier als een verborgen veld:

<form id="my_form" action="/something/todo/create" method="post">
<input name="__RequestVerificationToken" type="hidden" value="Cf..." /></form>

en verzend in het script:

function DoSomething() {
    $('#my_form').submit();
}

of gebruik een berichtmethode:

function DoSomething() {
    var form = $('#my_form');
    $.post("/something/todo/create", form.serialize());
}

Antwoord 5, Autoriteit 2%

In ASP.NET MVC Wanneer u @Html.AntiForgeryToken()Razor gebruikt, maakt een verborgen invoerveld met de naam __RequestVerificationTokenom tokens op te slaan. Als u een AJAX-implementatie wilt schrijven, moet u dit token zelf ophalen en doorgeven als een parameter op de server, zodat deze kan worden gevalideerd.

Stap 1: Krijg het token

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

Stap 2: Passeer het token in de AJAX-oproep

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')
      }
})
};

Opmerking : Het inhoudstype moet 'application/x-www-form-urlencoded; charset=utf-8'

Ik heb het project op GitHub geüpload; U kunt het downloaden en proberen.

https://github.com/lambda2016/ajaxvalidateAltiforyToken


Antwoord 6, Autoriteit 2%

    Functie DeletepersOnel (ID) {
        vargegevens = nieuwe formdata ();
        data.appdry ("__ aanvragenvergevorming", "@ htmlHelper.getantiforyToken ()");
        $ .ajax ({
          Type: 'Post',
          URL: '/ Person / Delete /' + ID,
          Gegevens: gegevens,
          Cache: false,
          ProcessData: FALSE,
          ContentType: FALSE,
          Succes: functie (resultaat) {
          }
        });
    }
    openbare statische klasse htmlhelper
    {
      openbare statische string GetantiforyToken ()
      {
        System.Text.Regularexpressions.Regulare = System.text.regularexpressions.Regex.match (system.web.helpers.antiforrolly.gethtml (). Tostring (), "(?: Waarde = \") (. *) (? : \ ")");
        if (value.success) 
{
          retourwaarde. Groepen [1]. Waarde;
        }
        opbrengst "";
      }
    }

Antwoord 7

In accountcontroller:

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

In beeld:

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

Het is belangrijk om contentTypein te stellen op 'application/x-www-form-urlencoded; charset=utf-8'of laat gewoon contentTypevan het object weg …


Antwoord 8

Ik weet dat dit een oude vraag is. Maar ik zal mijn antwoord toch toevoegen, misschien kan iemand zoals ik helpen.

Als u het resultaat van de post-actie van de controller niet wilt verwerken, zoals het aanroepen van de LoggOff-methode van de Accounts-controller, kunt u de volgende versie van @DarinDimitrov gebruiken ‘s antwoord:

@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>

Antwoord 9

Het token werkt niet als het door een andere controller is geleverd. bijv. het werkt niet als de weergave is geretourneerd door de Accounts-controller, maar u POSTnaar de Clients-controller.


Antwoord 10

Ik heb veel tijdelijke oplossingen geprobeerd en geen enkele werkte voor mij. De uitzondering was “Het vereiste formulierveld tegen vervalsing “__RequestVerificationToken”.

Wat me hielp was om van .ajax naar .post te veranderen:

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

Antwoord 11

Gebruik gerust onderstaande functie:

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

}


Antwoord 12

Maak een methode die verantwoordelijk is om token toe te voegen

var addAntiForgeryToken = function (data) {
    data.__RequestVerificationToken = $("[name='__RequestVerificationToken']").val();
    return data;
};

Gebruik nu deze methode terwijl u gegevens/parameters doorgeeft aan Action zoals hieronder

var Query = $("#Query").val();
        $.ajax({
            url: '@Url.Action("GetData", "DataCheck")',
            type: "POST",
            data: addAntiForgeryToken({ Query: Query }),
            dataType: 'JSON',
            success: function (data) {
            if (data.message == "Success") {
            $('#itemtable').html(data.List);
            return false;
            }
            },
            error: function (xhr) {
            $.notify({
            message: 'Error',
            status: 'danger',
            pos: 'bottom-right'
            });
            }
            });

Hier heeft mijn actie een enkele parameter van het tekenreekstype

   [HttpPost]
    [ValidateAntiForgeryToken]
    public JsonResult GetData( string Query)
    {

Antwoord 13

@using (Ajax.BeginForm("SendInvitation", "Profile",
        new AjaxOptions { HttpMethod = "POST", OnSuccess = "SendInvitationFn" },
        new { @class = "form-horizontal", id = "invitation-form" }))
    {
        @Html.AntiForgeryToken()
        <span class="red" id="invitation-result">@Html.ValidationSummary()</span>
        <div class="modal-body">
            <div class="row-fluid marg-b-15">
                <label class="block">                        
                </label>
                <input type="text" id="EmailTo" name="EmailTo" placeholder="[email protected]" value="" />
            </div>
        </div>
        <div class="modal-footer right">
            <div class="row-fluid">
                <button type="submit" class="btn btn-changepass-new">send</button>
            </div>
        </div>
    }

Other episodes