jQuery Ajax çağrıları ve Html.AntiForgeryToken ()


207

Uygulamamda internetteki bazı blog yazılarında okuduğum bilgileri izleyerek CSRF saldırılarını hafifletmeyi uyguladım . Özellikle bu yazı benim uygulamamın itici gücü oldu

Temel olarak bu makaleler ve öneriler, CSRF saldırısını önlemek için herkesin aşağıdaki kodu uygulaması gerektiğini söylüyor:

1) [ValidateAntiForgeryToken]POST Http fiilini kabul eden her eylemi ekleyin

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

2) <%= Html.AntiForgeryToken() %>Yardımcıyı sunucuya veri gönderen formların içine ekleyin

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

Neyse benim app bazı bölümlerinde hiç formu olmadan sunucuya jQuery ile Ajax POSTs yapıyorum. Bu, örneğin, kullanıcının belirli bir eylemi yapmak için bir resmi tıklatmasına izin verdiğim yerde olur.

Bir etkinlik listesi içeren bir tablom olduğunu varsayalım. "Etkinliği tamamlandı olarak işaretle" yazan tablonun bir sütununda bir görüntü var ve kullanıcı o etkinliği tıklattığında aşağıdaki örnekte olduğu gibi Ajax POST yapıyorum:

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

<%= Html.AntiForgeryToken() %>Bu durumlarda nasıl kullanabilirim ? Yardımcı çağrıyı Ajax çağrısının veri parametresinin içine dahil etmeli miyim?

Uzun yazı için özür dilerim ve yardım ettiğin için çok teşekkürler

DÜZENLE :

Gereğince jayrdub cevap aşağıdaki şekilde kullanmış

$("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) {
            // ....
        }
    });
});

David Hayden bağlantı artık 404'ler, o yeni bir CMS yaptığı blog göç, ama üzerinde tüm eski içerik göç etmedi anlaşılmaktadır.

Yanıtlar:


252

Bunun gibi basit bir js işlevi kullanıyorum

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

Sayfadaki her form jeton için aynı değere sahip olacağından, en üstteki kalıp sayfanıza böyle bir şey koyun

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

Sonra ajax çağrınızda do (ikinci örneğinizle eşleşecek şekilde düzenlenir)

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

6
Güzel, jeton getirmenin kapsüllenmesini seviyorum.
jball

2
@Lorenzo, özel verilerinizi aşağıdaki AddAntiForgeryTokengibi çağrının içine koyun :data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
jball

3
Sahtecilikle mücadele jetonunu her zaman artırmak için kullanmak ajaxSendveya geçersiz kılmak ne kadar kötü bir fikir olurdu ? Belki de sunucunuz için hedef olduğundan emin olmak için biraz kontrol ekleyerek . ajaxdataurl
ta.speot.is

1
Çıktı önbelleği kullanıyorsanız dikkatli olun.
Barbaros Alp

1
@SouhaiebBesbesleme jetonu tüm sayfalarda bir kullanıcı için aynı olmalıdır (ayarlanmış ve aynı kalan bir çerezle birlikte çalışır). Bu nedenle, sayfa başına birden fazla istek olması önemli değildir, yine de temel sayfanın yeniden yüklenmesi durumunda aynı olacaktır.
JeremyWeir

29

360Airwalk tarafından sağlanan çözümü seviyorum, ancak biraz geliştirilebilir.

İlk sorun, $.post()boş verilerle yaparsanız , jQuery bir Content-Typebaşlık eklemez ve bu durumda ASP.NET MVC jetonu alamaz ve kontrol edemez . Yani başlığın daima orada olduğundan emin olmalısınız.

Diğer bir gelişme, içeriğe sahip tüm HTTP fiillerinin desteklenmesidir : POST, PUT, DELETE vb. jeton.

$(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 haklısın, boş arama sonrası sorununu düşünmedim. giriş için teşekkürler. projemizde henüz sil / put kullanmamamız konusunda haklıydınız.
360Airwalk

2
Tüm jQuery.Ajax çağrılarına işlevi eklemek zorunda kalmadan beni kurtardığı için +1
Dragos Durlut

2
+1 Posterity için bir not olarak, .ajaxSend()"jQuery 1.8'den itibaren .ajaxSend () yöntemi yalnızca belgeye eklenmelidir" durumları için jQuery belgeleri. api.jquery.com/ajaxsend
RJ Cuthbertson

1
@Bronx optionsNihai ififadede listelenen nereden geliyor ? Teşekkürler.
hvaughan3

Bir sayfada birden çok form varsa bunu kullanmaya dikkat edin. Doküman yerine daha spesifik bir seçici çağrısıyla önce gönderirken değeri ayarlamanız gerekir.
Dan

22

Başka birçok cevap olduğunu biliyorum, ama bu makale güzel ve özlü ve sizi sadece bazılarını değil, tüm HttpPost'larınızı kontrol etmeye zorlar:

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

Form koleksiyonunu değiştirmeye çalışmak yerine HTTP üstbilgileri kullanır.

Sunucu

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

müşteri

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
Bağladığınız makalenin özniteliği, Bronx'un yanıtıyla birleştirildiğinde, bu soruna yönelik nihai DRY çözümüdür.
TugboatCaptain

2
Büyük bulmak. Cevabınızı kod parçacıkları içerecek şekilde düzenledim, böylece cevap kendi başına duruyor, ancak umarım insanlar makalenin geri kalanını da okuyacaktır. Bu çok temiz bir çözüm gibi görünüyor.
Tim Medora

teşekkürler Tim, mükemmel bir fikir, bir bağlantı öldüğünde ve cevap değersiz olduğunda onun sinir bozucu. Bunu tüm yeni cevaplarımda yapmaya başladım.
viggity

Bu MVC, WebAPI veya .NetCore mu? WebAPI 5
Myster

20

Burada gelişmiş bir büyücü gibi hissediyorum, ancak bu hala 4 yıl sonra MVC5'te bir sorun.

Ajax isteklerini doğru şekilde işlemek için sahtecilik önleme jetonunun ajax çağrılarında sunucuya iletilmesi gerekir. Kayıt verilerinize ve modellerinize entegre etmek dağınık ve gereksizdir. Jetonu özel bir başlık olarak eklemek temiz ve tekrar kullanılabilir - ve bunu her seferinde hatırlamak zorunda kalmayacak şekilde yapılandırabilirsiniz.

Bir istisna vardır - Göze batmayan ajax, ajax çağrıları için özel bir tedaviye ihtiyaç duymaz. Jeton normal gizli giriş alanına her zamanki gibi iletilir. Normal bir POST ile tamamen aynı.

_Layout.cshtml

_Layout.cshtml'de bu JavaScript bloğuna sahibim. Jetonu DOM'a yazmaz, bunun yerine MVC Yardımcısı'nın oluşturduğu gizli giriş hazır bilgisinden çıkarmak için jQuery kullanır. Üstbilgi adı olan Sihirli dize, öznitelik sınıfında sabit olarak tanımlanır.

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

BeforeSend işlevinde tek tırnak işareti kullanıldığına dikkat edin; işlenen giriş öğesi JavaScript değişmez değerini kıracak çift tırnak kullanır.

İstemci JavaScript'i

Bu yürütüldüğünde yukarıdaki beforeSend işlevi çağrılır ve AntiForgeryToken otomatik olarak istek başlıklarına eklenir.

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

Sunucu Kütüphanesi

Standart olmayan belirteci işlemek için özel bir özellik gerekir. Bu @ viggity'nin çözümünü temel alır, ancak göze batmayan ajax'ı doğru şekilde işler. Bu kod, ortak kitaplığınıza gizlenebilir

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

Sunucu / Denetleyici

Şimdi özelliği Eyleminize uygulamanız yeterlidir. Daha da iyisi, özelliği kontrolörünüze uygulayabilirsiniz ve tüm istekler doğrulanır.

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

Mükemmel çözüm, çok daha merkezi. Teşekkürler
David Freire

Neden yalnızca göreli URL'ler için başlık eklemek istediğinizi daha ayrıntılı olarak açıklayabilir misiniz? Bu kafamın üzerinden geçti. Harika bir çözüm!
MattM

relative, başlığın yalnızca kendi sunucunuza geri dönen isteklerde ayarlanmasını sağlar, ajax kurulumu jquery ile yapılan tüm istekleri kapsadığından, jeton veya CORS isteklerinde jetonun gönderilmesini istemiyoruz. Bu, mutlak URL'ler için de geçerli olabilir, ancak göreli alanın aynı alan adı olduğu garanti edilir.
D

1
@WillD Çözümünüzü beğendim, ancak biraz değiştirmek zorunda kaldım. $.ajaxSetupGenel bir beforesendolay işleyici tanımlamayı seçtiğiniz için üzerine yazabilirsiniz. Aynı zamanda ikinci bir işleyici ekleyebileceğiniz başka bir çözüm buldum . Güzel çalışır ve uygulamanızı bozmaz.
Viper

Müşterinin AntiForgery özelliğini doğrulayan ASP.net 5 sürümü olan var mı? Bu sürüm en son sürümde derlenmemiştir!
Rob McCabe

19

Html.AntiForgeryToken kullanmayın . Bunun yerine, ASP.NET MVC Uygulamasında Siteler Arası İstek Sahteciliği (CSRF) Saldırılarını Önleme konusunda açıklandığı gibi AntiForgery.GetTokens ve AntiForgery.Validate Web API'sini kullanın .


Modellenen sunucu model türünü yayınlanan AJAX JSON'a bağlayan denetleyici eylem yöntemleri için, uygun model bağlayıcının kullanılması için içerik türünün "application / json" olması gerekir. Ne yazık ki, bu [ValidateAntiForgeryToken] özniteliğinin gerektirdiği form verilerinin kullanılmasını engeller, bu nedenle yönteminiz çalışmasını sağlamak için bulabildiğim tek yol budur. Tek sorum şu: Hala bir web çiftliğinde veya birden fazla Azure web rolü örneğinde çalışıyor mu? @Edward veya bunun bir sorun olup olmadığını bilen var mı?
Richard B

@Edward Brey Neden kullanmamamız gerektiğini açıklayabilir misiniz?
Odys

4
@Odys: Html.AntiForgeryToken ile ilgili yanlış bir şey yoktur, ancak olumsuz yanları vardır: bir form gerektirir, jQuery gerektirir ve belgesiz Html.AntiForgeryToken uygulama ayrıntılarını varsayar. Yine de, birçok bağlamda sorun yok. "Html.AntiForgeryToken kullanma" ifadem muhtemelen çok güçlü çıkıyor. Benim anlamım, Web API ile birlikte kullanılması amaçlanmamışken, daha esnek AntiForgery.GetTokens.
Edward Brey

Teşekkürler! Ben bir MVC5 denetleyicisi için çalışmak için biraz değiştirmek zorunda kaldı, ama bu çözüm oldu
jao

3
Kesinlikle bir form gerektirmez. Bunun için DOM'yi adıyla ayrıştırmanız yeterlidir. Jquery kullanarak, veri nesnemin içine {__RequestVerificationToken: $ ("input [name = __ RequestVerificationToken]"). Val ()}
Anthony Mason

16

Bu gerçek problemi şu anki projemde uyguluyordum. kimliği doğrulanmış bir kullanıcı gerekli tüm ajax-POSTs için yaptım.

İlk kapalı ben çok sık kendimi tekrarlamak değil bu yüzden benim jquery ajax çağrıları kanca karar verdi. bu javascript snippet'i, tüm ajax (posta) çağrılarının talebe doğrulama doğrulama jetonumu eklemesini sağlar. Not: __RequestVerificationToken adı .Net çerçevesi tarafından kullanılır, böylece aşağıda gösterildiği gibi standart Anti-CSRF özelliklerini kullanabilirsiniz.

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

Yukarıdaki javascript için jetonun gerekli olduğu Görünümlerinizde sadece ortak HTML Yardımcısını kullanın. Temel olarak bu kodu istediğiniz yere ekleyebilirsiniz. Bir if (Request.IsAuthenticated) deyimi içine yerleştirdim:

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

Denetleyicinizde standart ASP.Net MVC Anti-CSRF mekanizmasını kullanın. Bu şekilde yaptım (aslında Tuz kullandım).

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

Firebug veya benzeri bir araçla POST isteklerinizin nasıl __RequestVerificationToken parametresinin eklendiğini kolayca görebilirsiniz.


15

Tek yapmanız gereken "__RequestVerificationToken" girdisinin POST isteğine dahil edildiğinden emin olmaktır. Bilgilerin diğer yarısı (yani kullanıcının çerezindeki simge) bir AJAX POST isteği ile otomatik olarak gönderilir.

Örneğin,

$("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
Bir MVC (Razor) sayfasından jQuery AJAX gönderisini denedikten sonra saatlerce çalıştıktan sonra bu benim için çalışanların en basit cevabı oldu. Jetondan sonra kendi veri alanlarınızı (veya sanırım viewModel'i) yeni bir veri parçası olarak ekleyin (ancak orijinal veri nesnesi içinde).
Ralph Bacon

AJAX işlevi bir Razor sayfasında değil .html sayfasındaysa bunu nasıl uygulayabilirim?
Bob the Builder

Html sayfanızda bir sunucu yoksa, AntiForgeryTokenyine de tartışmalıdır. Olursa (bu durumda nasıl bir tane aldığınızdan emin değilsiniz, ancak olduğunuzu varsayarak), o zaman yukarıdakiler işe yarayacaktır. Adı geçen belirteci bekleyen bir sunucuya istek gönderecek basit bir web sayfası oluşturmaya çalışıyorsanız ve sunucu adı geçen sayfayı oluşturmadıysa, şansınız kalmaz. Bu aslında AntiForgeryToken'ın amacı ...
jball

6

Bunu da yapabilirsiniz:

$("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) {
        // ....
        }
    });
});

Bu kullanıyor Razor, ancak WebFormssözdizimi kullanıyorsanız <%= %>etiketleri de kullanabilirsiniz


4

@ JBall'ın yol boyunca bana yardımcı olan cevabı hakkındaki yorumuma ek olarak, bu benim için çalışan son cevap. MVC ve Razor kullanıyorum ve jQuery AJAX kullanarak bir form gönderiyorum, bu yüzden bazı yeni sonuçlarla kısmi bir görünümü güncelleyebilir ve tam bir geri gönderme (ve sayfa titremesi) yapmak istemiyordum.

@Html.AntiForgeryToken()Formun içini her zamanki gibi ekleyin .

AJAX gönderim düğmesi kodum (yani bir onclick olayı):

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

Nasıl bir MvcJqGrid içeren kısmi görünüm ve nasıl yenileniyor (çok güçlü jqGrid ızgara ve bunun için parlak bir MVC sarıcı) güncellenen gösterir "başarı" eylem bıraktım.

Denetleyici yöntemim şöyle görünüyor:

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

Bir form olarak tüm formun verilerini POSTing hayranı olmak için itiraf etmeliyim ama bunu yapmak gerekirse o zaman bu çalışır bir yoludur. MVC sadece veri bağlama çok kolaylaştırır yerine 16 ayrı değerleri (ya da zayıf tip FormCollection) boyun eğmek yerine, tamam, sanırım. Daha iyi biliyorsanız, sağlam MVC C # kodu üretmek istiyorum gibi lütfen bana bildirin.


4

Bu çok akıllı fikri https://gist.github.com/scottrippey/3428114 adresinden bulmuştu . her $ .ajax çağrısı için isteği değiştirir ve jetonu ekler.

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

Yukarıdaki diğer alternatifleri denedim, bu benim için çözdü.
HostMyBus

Ancak if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {bir içerik türü belirtmemiş Ajax çağrıları yakalamak için eklemek zorunda
HostMyBus

3

Sunucudan Jeton almak için 1.Define İşlevi

@function
{

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

2. sunucuya göndermeden önce jeton alın ve başlığı ayarlayın

var token = '@TokenHeaderValue()';    

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

3. Post / get işlem yönteminde HttpRequestBase üzerinde Sunucu Doğrulaması

        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

Bu sorunun gönderilmesinden bu yana biraz zaman geçtiğini biliyorum, ancak AntiForgeryToken kullanımını tartışan ve kullanımı daha az zahmetli hale getiren gerçekten yararlı bir kaynak buldum. Ayrıca AJAX çağrılarına antiforgery jetonunu kolayca dahil etmek için jquery eklentisi sağlar:

ASP.NET MVC ve AJAX için Sahtecilikle Mücadele Tarifleri

Çok katkıda bulunmuyorum, ama belki birisi faydalı bulabilir.


Bu yazı bir mil uzunluğunda! Eminim harika ama tl; dr
İngilizDeveloper

1
Çok kötü, çünkü konuyu güzel bir şekilde kapsıyor. Sadece özelliği nasıl kullanacağınızı anlatmakla kalmaz, aynı zamanda hangi sorunu çözdüğünü açıklar ve doğru bir şekilde nasıl kullanacağınızı anlamanız için bağlam verir. Güvenlik söz konusu olduğunda, derinlemesine anlayışın önemli olduğunu düşünüyorum.
slawek

2
Önemli ise, insanları okumayı teşvik edecek şekilde yazılmalıdır;)
İngilizDeveloper

1

html'de ilk kullanım @ 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

İşte gördüğüm en kolay yol. Not: Görünümünüzde "@ Html.AntiForgeryToken ()" olduğundan emin olun

  $("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 çözümü için hafif iyileştirme. Bu, Anti Sahtecilik Jetonunu javascript işlevi içine yerleştirir, bu nedenle @ Html.AntiForgeryToken () işlevinin artık her görünüme dahil edilmesi gerekmez.

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

Bir silme yöntemi çalıştırmak için bir ajax yazı kullanıyorum (bir visjs zaman çizelgesinden olur ama bu relelvant değil). Ben sis budur:

Bu benim 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>

Buraya eklediğim tek şey @Html.AntiForgeryToken()belirtecin sayfada görünmesini sağlamaktı

Sonra ajax yazımda kullandım:

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

Bu, yayınlanan alanlara sayfa dışına çıkarılan belirteç değerini ekler

Bundan önce değeri başlıklara koymayı denedim ama aynı hatayı aldım

İyileştirmeler yayınlamaktan çekinmeyin. Bu kesinlikle anlayabileceğim basit bir yaklaşım gibi görünüyor


0

Pek çok gönderi burada, hiçbiri bana yardımcı olmadı, günler ve google günleri, ve yine de tüm uygulamayı sıfırdan yazarken noktaya geldim ve sonra Web.confg'deki bu küçük külçeyi fark ettim

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

Şimdi neden eklediğimi bilmiyorum, ancak o zamandan beri fark ettim, hata ayıklama modunda yok sayıldı ve üretim modunda değil (IE Bir Yerde IIS'ye Yüklendi)

Benim için çözüm 2 seçenekten biriydi, çünkü neden eklediğimi hatırlamıyorum, diğer şeylerin buna bağlı olmadığından emin olamıyorum ve ikincisi alan adı tamamen küçük olmalı ve ive yapılan gibi değil bir TLD olmalı * .localLookup.net'te

Belki yardımcı olur belki de değil. Umarım birine yardım eder


0

Buldum Çözüm ASPX için değil, Razor için değil, oldukça uyumlu bir konudur.

İsteğe AntiForgery ekleyerek çözdüm. HTML Yardımcısı çağrı ile bir HTML kimliği oluşturmaz

@Html.AntiForgeryToken()

Jetonu son talebe eklemek için AntiForgery kimliğini jquery ile gizli alana ekledim:

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

Bu, denetleyicinin [ValidateAntiForgeryToken] özniteliğiyle isteği kabul etmesine neden oldu


-3

Token hala bir acıdır, yukarıdaki örneklerin hiçbiri benim için kelime için işe yaramadı. Orada çok fazla var. Bu yüzden hepsini birleştirdim. IRC etrafında asılı bir formda bir @ Html.AntiforgeryTokun gerekir

Şu şekilde çözüldü:

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

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

Şüphe duyduğunuzda, daha fazla $ işareti ekleyin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.