jQuery के अजाक्स कॉल और Html.AntiForgeryToken ()


207

मैंने अपने एप में शमन को लागू कर दिया है CSRF हमलों के बाद लागू किया है जो मैंने इंटरनेट पर कुछ ब्लॉग पोस्ट पर पढ़ा है। विशेष रूप से ये पद मेरे कार्यान्वयन के चालक रहे हैं

मूल रूप से उन लेखों और सिफारिशों में कहा गया है कि सीएसआरएफ हमले को रोकने के लिए किसी को भी निम्नलिखित कोड लागू करना चाहिए:

1) [ValidateAntiForgeryToken]POST Http क्रिया को स्वीकार करने वाली प्रत्येक क्रिया पर जोड़ें

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction( SomeModel model ) {
}

2) <%= Html.AntiForgeryToken() %>हेल्पर को उन रूपों में जोड़ें जो डेटा को सर्वर में जमा करते हैं

<div style="text-align:right; padding: 8px;">
    <%= Html.AntiForgeryToken() %>
    <input type="submit" id="btnSave" value="Save" />
</div>

मेरे ऐप के कुछ हिस्सों में वैसे भी मैं jax के साथ Ajax POSTs सर्वर पर कर रहा हूँ, बिना किसी फॉर्म के। यह उदाहरण के लिए होता है जहां मैं उपयोगकर्ता को एक विशिष्ट कार्रवाई करने के लिए एक छवि पर क्लिक करने के लिए दे रहा हूं।

मान लीजिए कि मेरे पास गतिविधियों की सूची के साथ एक तालिका है। मेरे पास तालिका के एक स्तंभ पर एक छवि है जो कहती है "मार्क गतिविधि को पूरा करें" और जब उपयोगकर्ता उस गतिविधि पर क्लिक करता है तो मैं निम्नलिखित नमूने में Ajax POST कर रहा हूं:

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: {},
        success: function (response) {
            // ....
        }
    });
});

मैं <%= Html.AntiForgeryToken() %>इन मामलों में कैसे उपयोग कर सकता हूं ? क्या मुझे अजाक्स कॉल के डेटा पैरामीटर के अंदर सहायक कॉल शामिल करना चाहिए?

लंबी पोस्ट के लिए क्षमा करें और मदद करने के लिए बहुत बहुत धन्यवाद

संपादित करें :

जयरडब जवाब के अनुसार मैंने निम्नलिखित तरीके से उपयोग किया है

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: {
            AddAntiForgeryToken({}),
            id: parseInt($(this).attr("title"))
        },
        success: function (response) {
            // ....
        }
    });
});

डेविड हेडन लिंक अब 404s, ऐसा लगता है कि वह एक नया सीएमएस को अपने ब्लॉग चले गए है, लेकिन भर में पुरानी सामग्री की ओर पलायन नहीं किया।

जवाबों:


252

मैं इस तरह से एक साधारण js फ़ंक्शन का उपयोग करता हूं

AddAntiForgeryToken = function(data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

चूँकि किसी पृष्ठ पर प्रत्येक फॉर्म में टोकन के लिए समान मूल्य होगा, बस अपने शीर्ष-सर्वाधिक मास्टर पृष्ठ में कुछ ऐसा डालें

<%-- used for ajax in AddAntiForgeryToken() --%>
<form id="__AjaxAntiForgeryForm" action="#" method="post"><%= Html.AntiForgeryToken()%></form>  

फिर अपने अजाक्स कॉल में (अपने दूसरे उदाहरण से मिलान करने के लिए संपादित)

$.ajax({
    type: "post",
    dataType: "html",
    url: $(this).attr("rel"),
    data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
    success: function (response) {
        // ....
    }
});

6
अच्छा लगा, मुझे टोकन लाने का एनकैप्सुलेशन पसंद है।
जौब

2
AddAntiForgeryTokendata: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
@ लोरेंजो

3
एंटी-जालसाजी के टोकन के साथ हमेशा वृद्धि करने के लिए इसका उपयोग ajaxSendया ओवरराइड करना कितना बुरा होगा ? शायद यह सुनिश्चित करने के लिए कि आपके सर्वर के लिए किस्मत में कुछ चेक जोड़ना है। ajaxdataurl
ta.speot.is

1
यदि आप आउटपुट कैश का उपयोग करते हैं तो सावधान रहें।
बारब्रोस अल्प

1
@SouhaiebBesbes सत्यापन टोकन सभी पृष्ठों के उपयोगकर्ता के लिए समान होना चाहिए (यह कुकी के साथ संयोजन में काम करता है जो सेट होता है और समान रहता है)। अगर यह प्रति पृष्ठ कई अनुरोध हैं, तो इससे कोई फर्क नहीं पड़ता, यदि आधार पृष्ठ फिर भी लोड किया जाता है तो यह वही होगा।
जेरेमी वीर

29

मुझे 360Airwalk द्वारा प्रदान किया गया समाधान पसंद है, लेकिन इसमें थोड़ा सुधार किया जा सकता है।

पहली समस्या यह है कि यदि आप $.post()खाली डेटा बनाते हैं , तो jQuery Content-Typeहेडर नहीं जोड़ता है , और इस स्थिति में ASP.NET MVC टोकन प्राप्त करने और जांचने में विफल रहता है। इसलिए आपको यह सुनिश्चित करना होगा कि हेडर हमेशा बना रहे।

एक अन्य सुधार सामग्री के साथ सभी HTTP क्रियाओं का समर्थन है : POST, PUT, DELETE आदि। हालांकि आप अपने आवेदन में केवल POST का उपयोग कर सकते हैं, लेकिन एक सामान्य समाधान होना बेहतर है और सत्यापित करें कि आपके द्वारा किसी भी क्रिया के साथ प्राप्त सभी डेटा में एंटी-जालसाजी है। टोकन।

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $(document).ajaxSend(function (event, request, opt) {
        if (opt.hasContent && securityToken) {   // handle all verbs with content
            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
            // ensure Content-Type header is present!
            if (opt.contentType !== false || event.contentType) {
                request.setRequestHeader( "Content-Type", opt.contentType);
            }
        }
    });
});

1
+1 आप सही हैं, मैंने खाली पोस्ट कॉल समस्या के बारे में नहीं सोचा है। इनपुट के लिए धन्यवाद। आप इस बारे में सही थे कि हम अपने प्रोजेक्ट में अभी तक डिलीट / पुट का उपयोग नहीं करते हैं।
360Airwalk

2
+1 मुझे सभी jQuery में फ़ंक्शन जोड़ने से बचाने के लिए। AJAX कॉल
ड्रैगोस डर्लुत

2
+1 केवल .ajaxSend()पोस्टरिटी के लिए एक नोट के रूप में, राज्यों के लिए jQuery के दस्तावेज़ "jQuery के 1.8 के रूप में, .ajaxSend () विधि केवल दस्तावेज़ से जुड़ी होनी चाहिए।" api.jquery.com/ajaxsend
RJ Cuthbertson

1
@ ब्रोंक्स वह कहाँ से optionsआता है, जो अंतिम ifविवरण में सूचीबद्ध है ? धन्यवाद।
hugughan3

यदि आपके पास पृष्ठ पर कई रूप हैं, तो इसका उपयोग करने से बचें। आपको दस्तावेज़ के बजाय अधिक विशिष्ट चयनकर्ता कॉल के साथ पहले से मान में सेट करने की आवश्यकता होगी।
दान

22

मुझे पता है कि बहुत सारे अन्य उत्तर हैं, लेकिन यह लेख अच्छा है और संक्षिप्त है और आपको अपने सभी HttpPosts की जांच करने के लिए मजबूर करता है, न कि उनमें से कुछ:

http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/

यह फॉर्म संग्रह को संशोधित करने के बजाय HTTP हेडर का उपयोग करता है।

सर्वर

//make sure to add this to your global action filters
[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            //  Ajax POSTs and normal form posts have to be treated differently when it comes
            //  to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value 
                    : null;

                AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

ग्राहक

var token = $('[name=__RequestVerificationToken]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;

$.ajax({
    type: 'POST',
    url: '/Home/Ajax',
    cache: false,
    headers: headers,
    contentType: 'application/json; charset=utf-8',
    data: { title: "This is my title", contents: "These are my contents" },
    success: function () {
        ...
    },
    error: function () {
        ...
    }
});

4
ब्रोंक्स की प्रतिक्रिया के साथ संयुक्त लेख से विशेषता भी इस समस्या का अंतिम DRY समाधान है।
TugboatCaptain

2
शानदार खोज। मैंने आपके उत्तर को कोड स्निपेट में शामिल करने के लिए संपादित किया है ताकि उत्तर अपने आप ही खड़ा हो, लेकिन मुझे उम्मीद है कि लोग बाकी लेख भी पढ़ेंगे। यह एक बहुत साफ समाधान प्रतीत होता है।
टिम मेडोरा

धन्यवाद टिम, यह एक उत्कृष्ट विचार है, इसकी निराशा जब एक लिंक मृत हो जाती है और जवाब बेकार हो जाता है। मैंने अपने सभी नए उत्तरों पर यह करना शुरू कर दिया है।
13

क्या यह MVC, WebAPI या .NetCore है? मुझे
WebAPI

20

मैं यहां एक उन्नत नेक्रोमन्ट की तरह महसूस करता हूं, लेकिन एमवीसी 5 में 4 साल बाद भी यह एक मुद्दा है।

अजाक्स अनुरोधों को ठीक से संभालने के लिए एंटी-जालसाज टोकन को अजाक्स कॉल पर सर्वर से पारित करने की आवश्यकता है। इसे आपके पोस्ट डेटा और मॉडल में एकीकृत करना गन्दा और अनावश्यक है। एक कस्टम हेडर के रूप में टोकन जोड़ना साफ और पुन: प्रयोज्य है - और आप इसे कॉन्फ़िगर कर सकते हैं ताकि आपको हर बार ऐसा करने के लिए याद न करना पड़े।

एक अपवाद है - विनीत अजाक्स को अजाक्स कॉल के लिए विशेष उपचार की आवश्यकता नहीं है। टोकन को नियमित रूप से छिपे इनपुट क्षेत्र में सामान्य रूप से पास किया जाता है। नियमित POST के समान ही।

_Layout.cshtml

_Layout.cshtml में मेरे पास यह जावास्क्रिप्ट ब्लॉक है। यह DOM में टोकन नहीं लिखता है, बल्कि यह MVC हेल्पर द्वारा उत्पन्न छिपे इनपुट शाब्दिक से निकालने के लिए jQuery का उपयोग करता है। शीर्ष लेख नाम मैजिक स्ट्रिंग को विशेषता वर्ग में एक स्थिरांक के रूप में परिभाषित किया गया है।

<script type="text/javascript">
    $(document).ready(function () {
        var isAbsoluteURI = new RegExp('^(?:[a-z]+:)?//', 'i');
        //http://stackoverflow.com/questions/10687099/how-to-test-if-a-url-string-is-absolute-or-relative

        $.ajaxSetup({
            beforeSend: function (xhr) {
                if (!isAbsoluteURI.test(this.url)) {
                    //only add header to relative URLs
                    xhr.setRequestHeader(
                       '@.ValidateAntiForgeryTokenOnAllPosts.HTTP_HEADER_NAME', 
                       $('@Html.AntiForgeryToken()').val()
                    );
                }
            }
        });
    });
</script>

पूर्ववर्ती कार्य में एकल उद्धरणों के उपयोग पर ध्यान दें - जो इनपुट तत्व प्रदान किया गया है वह दोहरे उद्धरण चिह्नों का उपयोग करता है जो जावास्क्रिप्ट शाब्दिक को तोड़ देगा।

ग्राहक जावास्क्रिप्ट

जब यह ऊपर दिए गए पहले फ़ंक्शन को निष्पादित करता है और कहा जाता है, तो एंटीफ़ॉगररीटोकन को स्वचालित रूप से अनुरोध हेडर में जोड़ा जाता है।

$.ajax({
  type: "POST",
  url: "CSRFProtectedMethod",
  dataType: "json",
  contentType: "application/json; charset=utf-8",
  success: function (data) {
    //victory
  }
});

सर्वर लाइब्रेरी

गैर मानक टोकन को संसाधित करने के लिए एक कस्टम विशेषता आवश्यक है। यह @ viggity के समाधान पर बनाता है, लेकिन विनीत अजाक्स को सही ढंग से संभालता है। इस कोड को आपके सामान्य पुस्तकालय में रखा जा सकता है

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
    public const string HTTP_HEADER_NAME = "x-RequestVerificationToken";

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {

            var headerTokenValue = request.Headers[HTTP_HEADER_NAME];

            // Ajax POSTs using jquery have a header set that defines the token.
            // However using unobtrusive ajax the token is still submitted normally in the form.
            // if the header is present then use it, else fall back to processing the form like normal
            if (headerTokenValue != null)
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = antiForgeryCookie != null
                    ? antiForgeryCookie.Value
                    : null;

                AntiForgery.Validate(cookieValue, headerTokenValue);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute()
                    .OnAuthorization(filterContext);
            }
        }
    }
}

सर्वर / नियंत्रक

अब आप केवल अपने एक्शन के लिए विशेषता को लागू करते हैं। इससे भी बेहतर आप विशेषता को अपने नियंत्रक पर लागू कर सकते हैं और सभी अनुरोधों को मान्य किया जाएगा।

[HttpPost]
[ValidateAntiForgeryTokenOnAllPosts]
public virtual ActionResult CSRFProtectedMethod()
{
  return Json(true, JsonRequestBehavior.DenyGet);
}

सही समाधान, बहुत अधिक केंद्रीकृत। धन्यवाद
डेविड फ्रायर

क्या आप अधिक विस्तार से बता सकते हैं कि आप केवल सापेक्ष URL के लिए शीर्षलेख क्यों जोड़ना चाहते हैं? वह मेरे सिर पर चढ़ गया। महान समाधान!
मैट एसएपी

रिश्तेदार यह सुनिश्चित करता है कि हेडर केवल आपके स्वयं के सर्वर पर वापस जाने वाले अनुरोधों पर सेट है, क्योंकि ajax सेटअप jquery के साथ किए गए सभी अनुरोधों को शामिल करता है, हम नहीं चाहते कि टोकन को jsonp या CORS के आवेषण पर भेजा जाए। हो सकता है कि यह पूर्ण रूपेण भी सच हो, लेकिन रिश्तेदार एक ही डोमेन होने की गारंटी देते हैं।
विल डी

1
@WillD मुझे आपका समाधान पसंद आया, लेकिन इसे थोड़ा संशोधित करने के लिए मजबूर किया गया। क्योंकि आप $.ajaxSetupएक सामान्य beforesendईवेंट हैंडलर को परिभाषित करना चुनते हैं, ऐसा हो सकता है कि आप इसे ओवरराइट कर दें। मुझे एक और समाधान मिला जहां आप एक दूसरे हैंडलर को जोड़ सकते हैं जिसे भी बुलाया जाएगा। अच्छी तरह से काम करता है और आपके कार्यान्वयन को नहीं तोड़ता है।
वाइपर

क्या किसी के पास ASP.net ग्राहक के 5 संस्करण है जो एंटीफॉगररी विशेषता को मान्य करता है? यह संस्करण नवीनतम संस्करण में संकलित नहीं है!
रोब मैककेब

19

Html.AntiForgeryToken का उपयोग न करें । इसके बजाय, ASP.NET MVC अनुप्रयोग में क्रॉस-साइट रिक्वेस्ट फॉरगेरी (CSRF) हमलों को रोकने के रूप में वर्णित वेब API से AntiForgery.GetTokens और AntiForgery.Validate का उपयोग करें ।


नियंत्रक एक्शन विधियों के लिए जो मॉडल एक सर्वर मॉडल प्रकार को पोस्ट किए गए AJAX JSON में बाँधता है, उचित मॉडल बाइंडर के उपयोग के लिए "एप्लिकेशन / जोंस" के रूप में सामग्री प्रकार का होना आवश्यक है। दुर्भाग्य से, यह फॉर्म डेटा का उपयोग करने से रोकता है, जिसके लिए [ValidateAntiForgeryToken] विशेषता की आवश्यकता होती है, इसलिए आपका तरीका एकमात्र तरीका है जिससे मैं इसे काम कर पा सकता हूं। मेरा एकमात्र सवाल यह है कि क्या यह अभी भी एक वेब फ़ार्म या कई एज़्योर वेब रोल इंस्टेंस में काम करता है? क्या आपको @Edward, या किसी और को पता है कि क्या यह एक समस्या है?
रिचर्ड बी

@Edward ब्रे आप क्या हम इसका उपयोग नहीं करना चाहिए पर विस्तार से बता सकते हैं?
ओडीस

4
@Odys: Html.AntiForgeryToken के साथ स्वाभाविक रूप से कुछ भी गलत नहीं है, लेकिन इसमें डाउनसाइड्स हैं: एक फॉर्म की आवश्यकता है, jQuery की आवश्यकता है, और अनिर्दिष्ट Html.AntiForgeryToken कार्यान्वयन विवरणों को मानता है। फिर भी, यह कई संदर्भों में ठीक है। मेरा कथन "Html.AntiForgeryToken का उपयोग न करें" शायद बहुत मजबूत है। मेरा अर्थ यह है कि इसका उपयोग वेब एपीआई के साथ करने का इरादा नहीं है, जबकि अधिक लचीला एंटीफॉगररी.गेटटॉकेंस है।
एडवर्ड ब्रे

धन्यवाद! मुझे इसे MVC5 कंट्रोलर के लिए काम करने के लिए इसे थोड़ा बदलना पड़ा, लेकिन इसका हल था
jao

3
यह निश्चित रूप से एक फार्म की आवश्यकता नहीं है। आपको बस इसके लिए DOM को नाम से पार्स करना होगा। Jquery का उपयोग करते हुए, मैं इसे डेटा {__RequestVerificationToken: $ ("इनपुट [नाम = __ RequestVerificationToken]") के माध्यम से अपने डेटा ऑब्जेक्ट के अंदर जोड़ सकता हूं।) () ()}
एंथनी मैसन

16

मैं सिर्फ अपनी वर्तमान परियोजना में इस वास्तविक समस्या को लागू कर रहा था। मैंने यह सभी ajax-POST के लिए किया था जिसे एक प्रमाणीकृत उपयोगकर्ता की आवश्यकता थी।

सबसे पहले मैंने अपने jquery ajax कॉल्स को हुक करने का फैसला किया, इसलिए मैं खुद को अक्सर दोहराता नहीं हूं। यह जावास्क्रिप्ट स्निपेट सुनिश्चित करता है कि सभी ajax (पोस्ट) कॉल मेरे अनुरोध के सत्यापन टोकन को अनुरोध में जोड़ देंगे। नोट: नाम __RequestVerificationToken .Net फ्रेमवर्क द्वारा उपयोग किया जाता है ताकि मैं नीचे दिखाए गए अनुसार मानक एंटी-सीएसआरएफ सुविधाओं का उपयोग कर सकूं।

$(document).ready(function () {
    var securityToken = $('[name=__RequestVerificationToken]').val();
    $('body').bind('ajaxSend', function (elm, xhr, s) {
        if (s.type == 'POST' && typeof securityToken != 'undefined') {
            if (s.data.length > 0) {
                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
            else {
                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
        }
    });
});

आपके दृश्यों में जहां आपको उपरोक्त जावास्क्रिप्ट के लिए उपलब्ध टोकन की आवश्यकता होती है, बस सामान्य एचटीएमएल-हेल्पर का उपयोग करें। आप मूल रूप से इस कोड को जोड़ सकते हैं जहाँ भी आप चाहते हैं। मैंने इसे एक if (Request.IsAuthenticated) विवरण के भीतर रखा:

@Html.AntiForgeryToken() // you can provide a string as salt when needed which needs to match the one on the controller

अपने नियंत्रक में बस मानक ASP.Net MVC एंटी-सीएसआरएफ तंत्र का उपयोग करें। मैंने इसे इस तरह किया (हालांकि मैं वास्तव में नमक का इस्तेमाल करता था)।

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public JsonResult SomeMethod(string param)
{
    // do something
    return Json(true);
}

फायरबग या इसी तरह के टूल से आप आसानी से देख सकते हैं कि आपके POST अनुरोधों में __RequestVerificationToken पैरामीटर को कैसे जोड़ा गया है।


15

मुझे लगता है कि आपको यह सुनिश्चित करना होगा कि "__RequestVerificationToken" इनपुट POST अनुरोध में शामिल है। जानकारी का दूसरा हिस्सा (यानी उपयोगकर्ता की कुकी में टोकन) पहले से ही AJAX POST अनुरोध के साथ स्वचालित रूप से भेजा जाता है।

उदाहरण के लिए,

$("a.markAsDone").click(function (event) {
    event.preventDefault();
    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: { 
            "__RequestVerificationToken":
            $("input[name=__RequestVerificationToken]").val() 
        },
        success: function (response) {
            // ....
        }
    });
});

1
कई घंटों के बाद jVC AJAX के साथ MVC (रेजर) पेज के भीतर प्रयोग करने के बाद यह मेरे लिए काम करने वाले सभी का सबसे सरल उत्तर था। डेटा के एक नए टुकड़े (लेकिन मूल डेटा ऑब्जेक्ट के भीतर) के रूप में टोकन के बाद बस अपने स्वयं के डेटा फ़ील्ड (या viewModel I suppose) को शामिल करें।
राल्फ बेकन

यदि AJAX फ़ंक्शन .html पेज में है और रेज़र पेज नहीं तो मैं इसे कैसे लागू करूंगा?
बॉब द बिल्डर

यदि आपके HTML पेज में सर्वर की आपूर्ति नहीं है, तो AntiForgeryTokenयह किसी भी तरह से लूट लिया जाएगा। यदि यह (यह सुनिश्चित नहीं है कि आप उस स्थिति में एक कैसे हो, लेकिन यह मानते हुए कि आप हैं), तो उपरोक्त ठीक काम करेगा। यदि आप एक साधारण वेबपृष्ठ बनाने का प्रयास कर रहे हैं, जो एक सर्वर से अनुरोध करेगा, जो यह कहते हुए टोकन की उम्मीद करेगा, और सर्वर ने कहा पृष्ठ उत्पन्न नहीं किया है, तो आप भाग्य से बाहर हैं। यह अनिवार्य रूप से
एंटीफॉर्गरीटोकन

6

आप यह भी कर सकते हैं:

$("a.markAsDone").click(function (event) {
    event.preventDefault();

    $.ajax({
        type: "post",
        dataType: "html",
        url: $(this).attr("rel"),
        data: $('<form>@Html.AntiForgeryToken()</form>').serialize(),
        success: function (response) {
        // ....
        }
    });
});

यह उपयोग कर रहा है Razor, लेकिन अगर आप WebFormsसिंटैक्स का उपयोग कर रहे हैं तो आप केवल <%= %>टैग का उपयोग कर सकते हैं


4

आगे @ JBall के जवाब के खिलाफ मेरी टिप्पणी जिसने मुझे रास्ते में मदद की, यह अंतिम जवाब है जो मेरे लिए काम करता है। मैं MVC और रेजर का उपयोग कर रहा हूं और मैं jQuery AJAX का उपयोग करके एक फॉर्म सबमिट कर रहा हूं ताकि मैं कुछ नए परिणामों के साथ एक आंशिक दृश्य अपडेट कर सकूं और मैं एक पूर्ण पोस्टबैक (और पेज फ़्लिकर) नहीं करना चाहता था।

@Html.AntiForgeryToken()हमेशा की तरह फॉर्म के अंदर जोड़ें ।

मेरा AJAX सबमिशन बटन कोड (यानी एक ऑनक्लिक ईवेंट) है:

//User clicks the SUBMIT button
$("#btnSubmit").click(function (event) {

//prevent this button submitting the form as we will do that via AJAX
event.preventDefault();

//Validate the form first
if (!$('#searchForm').validate().form()) {
    alert("Please correct the errors");
    return false;
}

//Get the entire form's data - including the antiforgerytoken
var allFormData = $("#searchForm").serialize();

// The actual POST can now take place with a validated form
$.ajax({
    type: "POST",
    async: false,
    url: "/Home/SearchAjax",
    data: allFormData,
    dataType: "html",
    success: function (data) {
        $('#gridView').html(data);
        $('#TestGrid').jqGrid('setGridParam', { url: '@Url.Action("GetDetails", "Home", Model)', datatype: "json", page: 1 }).trigger('reloadGrid');
    }
});

मैंने "सफलता" कार्रवाई को छोड़ दिया है क्योंकि यह दिखाता है कि आंशिक दृश्य को कैसे अपडेट किया जा रहा है जिसमें एक MvcJqGrid शामिल है और यह कैसे ताज़ा किया जा रहा है (बहुत शक्तिशाली jqGrid ग्रिड और यह इसके लिए एक शानदार MVC आवरण है)।

मेरी नियंत्रक विधि इस प्रकार है:

    //Ajax SUBMIT method
    [ValidateAntiForgeryToken]
    public ActionResult SearchAjax(EstateOutlet_D model) 
    {
        return View("_Grid", model);
    }

मुझे एक मॉडल के रूप में पूरे फॉर्म के डेटा को पोस्ट करने का प्रशंसक नहीं बनना है, लेकिन अगर आपको इसे करने की आवश्यकता है तो यह एक तरीका है जो काम करता है। एमवीसी केवल 16 व्यक्तिगत मूल्यों (या एक कमजोर-टाइप किए गए फॉर्मकॉलिनेशन) को छोड़ने के बजाय डेटा को इतना आसान बनाता है कि यह ठीक है, मुझे लगता है। यदि आप बेहतर जानते हैं तो कृपया मुझे बताएं क्योंकि मैं MVC C # कोड का उत्पादन करना चाहता हूं।


4

https://gist.github.com/scottrippey/3428114 से हर $ .ajax के लिए यह बहुत ही चतुर विचार मिला। कॉल इसे अनुरोध को संशोधित करता है और टोकन जोड़ता है।

// Setup CSRF safety for AJAX:
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    if (options.type.toUpperCase() === "POST") {
        // We need to add the verificationToken to all POSTs
        var token = $("input[name^=__RequestVerificationToken]").first();
        if (!token.length) return;

        var tokenName = token.attr("name");

        // If the data is JSON, then we need to put the token in the QueryString:
        if (options.contentType.indexOf('application/json') === 0) {
            // Add the token to the URL, because we can't add it to the JSON data:
            options.url += ((options.url.indexOf("?") === -1) ? "?" : "&") + token.serialize();
        } else if (typeof options.data === 'string' && options.data.indexOf(tokenName) === -1) {
            // Append to the data string:
            options.data += (options.data ? "&" : "") + token.serialize();
        }
    }
});

मैंने ऊपर दिए गए अन्य विकल्पों में से कई की कोशिश की, यही मेरे लिए इसे हल किया है।
HostMyBus

हालाँकि मुझे if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {अजाक्स कॉल्स को पकड़ने के लिए जोड़ना था जो एक कंटेंट टाइप को निर्दिष्ट नहीं किया था
HostMyBus

3

सर्वर से टोकन प्राप्त करने के लिए 1.Define फ़ंक्शन

@function
{

        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
}

2.Get टोकन और सर्वर पर भेजने से पहले हेडर सेट करें

var token = '@TokenHeaderValue()';    

       $http({
           method: "POST",
           url: './MainBackend/MessageDelete',
           data: dataSend,
           headers: {
               'RequestVerificationToken': token
           }
       }).success(function (data) {
           alert(data)
       });

3. HttpRequestBase पर Onserver Validation जिस विधि से आप पोस्ट / हैंडल करते हैं

        string cookieToken = "";
        string formToken = "";
        string[] tokens = Request.Headers["RequestVerificationToken"].Split(':');
            if (tokens.Length == 2)
            {
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
            }
        AntiForgery.Validate(cookieToken, formToken);

1

मुझे पता है कि इस प्रश्न को पोस्ट किए जाने के बाद कुछ समय हो गया है, लेकिन मुझे वास्तव में उपयोगी संसाधन मिला, जो एंटीफॉरगेरीटोकैन के उपयोग पर चर्चा करता है और इसका उपयोग करने के लिए कम परेशानी पैदा करता है। यह AJAX कॉल में आसानी से एंटिफॉर्गी टोकन सहित jquery प्लगइन प्रदान करता है:

ASP.NET MVC और AJAX के लिए एंटी-फोर्जरी अनुरोध व्यंजनों

मैं ज्यादा योगदान नहीं दे रहा हूं, लेकिन शायद कोई इसे उपयोगी समझेगा।


वह पद एक मील लंबे जैसा है! मुझे यकीन है कि यह बहुत अच्छा है लेकिन tl; dr
BritishDeveloper

1
बहुत बुरा है, क्योंकि यह अच्छी तरह से विषय को कवर करता है। यह न केवल आपको बताता है कि फीचर का उपयोग कैसे करना है, बल्कि यह बताता है कि यह किस समस्या को ठीक करता है और आपको यह समझने के लिए संदर्भ देता है कि इसे सही तरीके से कैसे उपयोग किया जाए। जब सुरक्षा की बात आती है तो मुझे लगता है कि गहराई से समझ जरूरी है।
स्लावेक

2
अगर यह महत्वपूर्ण है तो इसे इस तरह से लिखा जाना चाहिए जो लोगों को इसे पढ़ने के लिए प्रोत्साहित करे;)
ब्रिटिशड्यूप्लर

1

html में पहली बार @ Html.AntiForgeryToken () का उपयोग करें

 $.ajax({
        url: "@Url.Action("SomeMethod", "SomeController")",
        type: 'POST',
        data: JSON.stringify(jsonObject),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        async: false,
        beforeSend: function (request) {
            request.setRequestHeader("RequestVerificationToken", $("[name='__RequestVerificationToken']").val());
        },
        success: function (msg) {
            alert(msg);
        }

1

यहाँ मैंने देखा सबसे आसान तरीका है। नोट: सुनिश्चित करें कि आपके पास अपने दृश्य में "@ Html.AntiForgeryToken ()" है

  $("a.markAsDone").click(function (event) {
        event.preventDefault();
        var sToken = document.getElementsByName("__RequestVerificationToken")[0].value;
        $.ajax({
            url: $(this).attr("rel"),
            type: "POST",
            contentType: "application/x-www-form-urlencoded",
            data: { '__RequestVerificationToken': sToken, 'id': parseInt($(this).attr("title")) }
        })
        .done(function (data) {
            //Process MVC Data here
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            //Process Failure here
        });
    });

0

360Airwalk समाधान के लिए थोड़ा सुधार। यह जावास्क्रिप्ट फ़ंक्शन के भीतर एंटी फ़ॉगररी टोकन को इम्बेड करता है, इसलिए @ Html.AntiForgeryToken () को अब हर दृश्य पर शामिल करने की आवश्यकता नहीं है।

$(document).ready(function () {
    var securityToken = $('@Html.AntiForgeryToken()').attr('value');
    $('body').bind('ajaxSend', function (elm, xhr, s) {
        if (s.type == 'POST' && typeof securityToken != 'undefined') {
            if (s.data.length > 0) {
                s.data += "&__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
            else {
                s.data = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
            }
        }
    });
});

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

0

मैं एक नष्ट विधि को चलाने के लिए ajax पोस्ट का उपयोग कर रहा हूं (यह एक वीजेएस समयरेखा से होता है लेकिन यह पुनः प्रकाशित नहीं होता है)। यह वही है जो मैं:

यह मेरा Index.cshtml है

@Scripts.Render("~/bundles/schedule")
@Styles.Render("~/bundles/visjs")
@Html.AntiForgeryToken()

<!-- div to attach schedule to -->
<div id='schedule'></div>

<!-- div to attach popups to -->
<div id='dialog-popup'></div>

यहाँ मैंने जो कुछ भी जोड़ा था @Html.AntiForgeryToken() पृष्ठ में एक टोकन प्रदर्शित करना

फिर मेरे ajax पोस्ट में मैंने इस्तेमाल किया:

$.ajax(
    {
        type: 'POST',
        url: '/ScheduleWorks/Delete/' + item.id,
        data: {
            '__RequestVerificationToken': 
            $("input[name='__RequestVerificationToken']").val()
              }
     }
);

जो पोस्ट किए गए फ़ील्ड में, पृष्ठ से स्क्रैप किए गए टोकन मान को जोड़ता है

इससे पहले मैंने हेडर में मूल्य डालने की कोशिश की लेकिन मुझे वही त्रुटि मिली

बेहिचक पोस्ट सुधार करें। यह निश्चित रूप से एक सरल दृष्टिकोण प्रतीत होता है जिसे मैं समझ सकता हूं


0

ठीक है यहाँ बहुत सारी पोस्टें, उनमें से किसी ने भी मेरी मदद नहीं की, दिन और दिन गूगल के, और फिर भी आगे मुझे इस बात की जानकारी नहीं थी कि स्क्रैच से पूरे ऐप को राइट-राइट किया जाए, और फिर मैंने अपने Web.confg में इस छोटी सी डली पर ध्यान दिया

 <httpCookies requireSSL="false" domain="*.localLookup.net"/>

अब मुझे नहीं पता कि मैंने इसे क्यों जोड़ा लेकिन मैंने देखा है, इसके डिबग मोड में अनदेखा किया गया है और उत्पादन मोड में नहीं (आईई कहीं स्थापित किया गया है)

मेरे लिए समाधान 2 विकल्पों में से एक था, क्योंकि मुझे याद नहीं है कि मैंने इसे क्यों जोड़ा है मैं यह सुनिश्चित नहीं कर सकता कि अन्य चीजें इस पर निर्भर न हों, और दूसरा डोमेन नाम सभी निचले मामले में होना चाहिए और एक TLD ive पसंद नहीं है * .localLookup.net में

शायद यह मदद करता है शायद यह नहीं है। मुझे आशा है कि यह किसी की मदद करता है


0

मैंने जो सॉल्यूशन पाया वह ASPX के लिए नहीं है, बल्कि रेजर के लिए है, लेकिन काफी कम्फर्टेबल मुद्दा है।

मैंने अनुरोध में एंटीफॉगररी जोड़कर इसे हल किया। HTML हेल्पर कॉल के साथ एक HTML आईडी नहीं बनाता है

@Html.AntiForgeryToken()

पोस्टक्वेस्ट में टोकन जोड़ने के लिए मैंने सिर्फ एंटीफॉगररी आईडी को jquery के साथ छिपे हुए फ़ील्ड में जोड़ा:

$("input[name*='__RequestVerificationToken']").attr('id', '__AjaxAntiForgeryForm');

इसके कारण नियंत्रक को [ValidateAntiForgeryToken] विशेषता के साथ अनुरोध स्वीकार करना पड़ा


-3

AntiforgeryToken अभी भी एक दर्द है, ऊपर दिए गए उदाहरणों में से कोई भी मेरे लिए शब्द के लिए काम नहीं करता है। वहाँ के लिए बहुत सारे। इसलिए मैंने उन सभी को मिला दिया। एक @ Html.AntiforgeryToken की आवश्यकता होती है, जो कि iirc के चारों ओर लटका हुआ है

इस प्रकार हल किया गया:

function Forgizzle(eggs) {
    eggs.__RequestVerificationToken =  $($("input[name=__RequestVerificationToken]")[0]).val();
    return eggs;
}

$.ajax({
            url: url,
            type: 'post',
            data: Forgizzle({ id: id, sweets: milkway }),
});

जब संदेह में, अधिक $ संकेत जोड़ें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.