Programing

Ajax post ASP.NET MVC에 antiforgerytoken 포함

lottogame 2020. 6. 12. 22:08
반응형

Ajax post ASP.NET MVC에 antiforgerytoken 포함


AntiForgeryToken에 아약스 문제가 있습니다. ASP.NET MVC 3을 사용하고 있습니다. jQuery Ajax 호출 및 Html.AntiForgeryToken () 에서 솔루션을 시도했습니다 . 해당 솔루션을 사용하여 이제 토큰이 전달됩니다.

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

[ValidateAntiForgeryToken]데이터 (토큰 포함)가 매개 변수로 컨트롤러에 전달되는지 확인 하기 위해 속성을 제거하면 매개 변수가 전달되고 있음을 알 수 있습니다. 그러나 어떤 이유로 든 A required anti-forgery token was not supplied or was invalid.속성을 다시 넣으면 메시지가 계속 나타납니다.

어떤 아이디어?

편집하다

위조 방지 토큰이 양식 내부에서 생성되고 있지만 제출 조치를 사용하여 제출하지 않습니다. 대신 jquery를 사용하여 토큰의 가치를 얻은 다음 아약스를 게시하려고합니다.

토큰을 포함하고 맨 위 마스터 페이지에있는 양식은 다음과 같습니다.

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

에를 잘못 지정 contentType했습니다 application/json.

이것이 어떻게 작동하는지에 대한 예는 다음과 같습니다.

제어 장치:

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>

내가 한 또 다른 (자바 스크립트) 접근 방식은 다음과 같습니다.

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

문자열을 반환합니다

__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"

이렇게 사용할 수 있습니다

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

그리고 그것은 작동하는 것 같습니다!


너무 간단합니다! @Html.AntiForgeryToken()html 코드에서 사용 하면 서버 가이 페이지에 서명 했으며이 특정 페이지에서 서버로 전송 된 각 요청에는 해커가 위조 요청을 보낼 수 없다는 표시가 있음을 의미합니다. 이 페이지가 서버에 의해 인증 되려면 두 단계를 거쳐야합니다.

1. 이름이 붙은 매개 변수를 보내고 __RequestVerificationToken아래에서 값 사용 코드를 가져 옵니다 .

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

예를 들어 아약스 호출

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

2 단계는 [ValidateAntiForgeryToken]


Asp.Net Core에서는 다음과 같이 문서화 된대로 토큰을 직접 요청할 수 있습니다 .

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

그리고 자바 스크립트에서 사용하십시오 :

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

다음과 같이 권장되는 전역 필터를 추가 할 수 있습니다 .

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



        DeletePersonel (id) {함수

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

                $ .ajax ({
                    유형 : 'POST',
                    url : '/ Personel / Delete /'+ id,
                    데이터 : 데이터,
                    캐시 : false,
                    processData : false,
                    contentType : false,
                    성공 : 기능 (결과) {

                    }
                });

        }
    

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

In Asp.Net MVC when you use @Html.AntiForgeryToken() Razor creates a hidden input field with name __RequestVerificationToken to store tokens. If you want to write an AJAX implementation you have to fetch this token yourself and pass it as a parameter to the server so it can be validated.

Step 1: Get the token

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

Step 2: Pass the token in the AJAX call

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: The content type should be 'application/x-www-form-urlencoded; charset=utf-8'

I have uploaded the project on Github; you can download and try it.

https://github.com/lambda2016/AjaxValidateAntiForgeryToken


I know this is an old question. But I will add my answer anyway, might help someone like me.

If you dont want to process the result from the controller's post action, like calling the LoggOff method of Accounts controller, you could do as the following version of @DarinDimitrov 's answer:

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

I tried a lot of workarrounds and non of them worked for me. The exception was "The required anti-forgery form field "__RequestVerificationToken" .

What helped me out was to switch form .ajax to .post:

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

Feel free to use the function below:

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

}


In Account controller:

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

In View:

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

It is important to set contentType to 'application/x-www-form-urlencoded; charset=utf-8' or just omit contentTypefrom the object ...


The token won't work if it was supplied by a different controller. E.g. it won't work if the view was returned by the Accounts controller, but you POST to the Clients controller.

참고URL : https://stackoverflow.com/questions/14473597/include-antiforgerytoken-in-ajax-post-asp-net-mvc

반응형