jQuery Ajax呼び出しとHtml.AntiForgeryToken()


207

私は自分のアプリに、インターネット上のブログ投稿で読んだ情報に従って、CSRF攻撃の緩和策を実装しました。特にこれらの投稿は私の実装の原動力となっています

基本的に、これらの記事と推奨事項では、CSRF攻撃を防ぐには、次のコードを実装する必要があるとしています。

1)[ValidateAntiForgeryToken]POST Http動詞を受け入れるon onアクションを追加します

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

とにかく、私のアプリの一部で、フォームをまったく持たずにサーバーに対してjQueryでAjax POSTを実行しています。これは、たとえば、ユーザーに画像をクリックして特定のアクションを実行させる場合に発生します。

アクティビティのリストを含むテーブルがあるとします。テーブルの列に「アクティビティに完了のマークを付ける」という画像があり、ユーザーがそのアクティビティをクリックすると、次のサンプルのようにAjax POSTを実行しています。

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

<%= Html.AntiForgeryToken() %>これらの場合にどのように使用できますか?Ajax呼び出しのデータパラメーター内にヘルパー呼び出しを含める必要がありますか?

長い投稿でごめんね、助けてくれてありがとう

編集

あたりとしてjayrdub答え私は、次のように使用していました

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

デビッド・ヘイデンリンクは今404エラーは、彼が新しいCMSへの彼のブログを移行していますが、以上のすべての古いコンテンツを移行しなかったことが表示されます。

回答:


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呼び出しで(2番目の例と一致するように編集)

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

6
いいですね、トークン取得のカプセル化が好きです。
jball

2
@Lorenzoは、への呼び出し内のカスタムデータを置くAddAntiForgeryTokenので、同様に、:data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
jball

3
偽造防止トークンで常に増強するために使用ajaxSendまたはオーバーライドajaxすることは、どのくらい悪い考えでしょうdataか?多分それがurlあなたのサーバーに宛てられていることを確認するためにいくつかのチェックを追加します。
ta.speot.is 2013

1
出力キャッシュを使用する場合は注意してください。
Barbaros Alp 14年

1
@SouhaiebBesbes検証トークンは、すべてのページでユーザーに対して同じである必要があります(設定されたままのCookieと連動して機能します)。したがって、ページごとに複数のリクエストがあるかどうかは関係ありません。ベースページがリロードされた場合も同じです。
JeremyWeir 2015

29

私は360Airwalkが提供するソリューションを気に入っていますが、少し改善される可能性があります。

最初の問題は、$.post()空のデータで作成した場合、jQueryがContent-Typeヘッダーを追加しないことです。この場合、ASP.NET MVCはトークンの受信とチェックに失敗します。したがって、ヘッダーが常にそこにあることを確認する必要があります。

別の改善点は、POST、PUT、DELETEなどのコンテンツを含むすべてのHTTP動詞のサポートです。アプリケーションでは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 2012

2
すべてのjQuery.Ajax呼び出しに関数を追加する必要をなくすための+1
Dragos Durlut

2
+1後世のメモと同様に、jQueryのドキュメントに.ajaxSend()は「jQuery 1.8以降、.ajaxSend()メソッドはドキュメントにのみ添付する必要があります」と記載されています。api.jquery.com/ajaxsend
RJ Cuthbertson

1
@Bronx options最終的なif声明に記載されている出所はどこですか?ありがとう。
hvaughan3 2016

ページに複数のフォームがある場合は、これを使用することに注意してください。ドキュメントの代わりに、より具体的なセレクター呼び出しを使用してbeforeSendの値を設定する必要があります。
Dan

22

他にもたくさんの回答があることは承知していますが、この記事は素晴らしく簡潔なので、一部だけでなくすべてのHttpPostを確認する必要があります。

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 14

2
素晴らしい発見。コードスニペットが含まれるように回答を編集しましたので、回答はそれ自体が自明ですが、記事の残りの部分も読んでいただければ幸いです。これは非常にクリーンなソリューションのようです。
Tim Medora 2014

Timに感謝します。これは素晴らしいアイデアです。リンクが機能しなくなり、答えが役に立たなくなるとイライラします。私はすべての新しい答えでこれを始めました。
2014

これはMVC、WebAPI、または.NetCoreですか?WebAPI 5の正しい名前空間を取得できません
Myster

20

私はここでは高度なネクロマンサーのように感じますが、これはMVC5での4年後の問題です。

ajaxリクエストを適切に処理するには、偽造防止トークンをajax呼び出しでサーバーに渡す必要があります。それを投稿データやモデルに統合するのは面倒で不要です。トークンをカスタムヘッダーとして追加することは、クリーンで再利用可能です。また、毎回行うことを覚えておく必要がないように構成できます。

例外があります-控えめなajaxはajax呼び出しの特別な処理を必要としません。トークンは、通常の非表示の入力フィールドで通常どおり渡されます。通常のPOSTとまったく同じです。

_Layout.cshtml

_layout.cshtmlには、このJavaScriptブロックがあります。トークンをDOMに書き込むのではなく、jQueryを使用して、MVCヘルパーが生成する非表示の入力リテラルからトークンを抽出します。ヘッダー名であるマジック文字列は、属性クラスで定数として定義されています。

<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関数での単一引用符の使用に注意してください。レンダリングされる入力要素は、JavaScriptリテラルを壊す二重引用符を使用します。

クライアントJavaScript

これが実行されると、上記のbeforeSend関数が呼び出され、AntiForgeryTokenがリクエストヘッダーに自動的に追加されます。

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

サーバーライブラリ

非標準のトークンを処理するには、カスタム属性が必要です。これは@viggityのソリューションに基づいていますが、控えめなajaxを正しく処理します。このコードは、共通ライブラリに隠しておくことができます

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

完全なソリューション、はるかに集中化。ありがとう
David Freire

相対URLのヘッダーのみを追加する理由を詳しく説明できますか?それは私の頭を超えました。素晴らしい解決策!
MattM、2015

相対は、ヘッダーが自分のサーバーに戻るリクエストにのみ設定されることを保証します。ajaxセットアップはjqueryで行われたすべてのリクエストをカバーするため、トークンがjsonpまたはCORS requetsで送信されないようにします。これは絶対URLにも当てはまるかもしれませんが、相対URLは同じドメインであることが保証されています。
2015

1
@WillD私はあなたのソリューションが好きでしたが、少し修正することを余儀なくされました。$.ajaxSetup一般的なbeforesendイベントハンドラーを定義することを選択するため、それを上書きする可能性があります。呼び出される2番目のハンドラーを追加できる別の解決策を見つけました。うまく機能し、実装を壊しません。
Viper

誰かがASP.net 5バージョンの顧客検証AntiForgery属性を持っていますか?このバージョンは最新バージョンではコンパイルできません!
Rob McCabe

19

Html.AntiForgeryTokenは使用しないでください。代わりに、ASP.NET MVCアプリケーションでのクロスサイトリクエストフォージェリ(CSRF)攻撃の防止で説明されているように、Web APIからAntiForgery.GetTokensおよびAntiForgery.Validateを使用してください


サーバーモデルタイプを投稿されたAJAX JSONにモデルバインドするコントローラーアクションメソッドの場合、適切なモデルバインダーを使用するには、コンテンツタイプを "application / json"にする必要があります。残念ながら、これは[ValidateAntiForgeryToken]属性に必要なフォームデータの使用を不可能にするため、私が見つけた唯一の方法があなたのメソッドです。私の唯一の質問は、それはまだWebファームまたは複数のAzure Webロールインスタンスで動作しますか?あなたは@エドワード、または他の誰かがこれが問題であるかどうか知っていますか?
リチャードB

@Edward Breyなぜ使用してはいけないのか詳しく説明していただけますか?
Odys 2014

4
@Odys:Html.AntiForgeryTokenには本質的に問題はありませんが、欠点があり、フォームが必要であり、jQueryが必要であり、文書化されていないHtml.AntiForgeryToken実装の詳細を想定しています。それでも、多くの状況では問題ありません。「Html.AntiForgeryTokenを使用しないでください」という私の発言は、おそらく強すぎます。私の意味は、より柔軟なAntiForgery.GetTokensがWeb APIでの使用を意図していないことです。
エドワードブレイ

どうも!MVC5コントローラーで機能させるには少し変更する必要がありましたが、これが解決策でした
jao

3
確かにフォームは必要ありません。DOMを名前で解析するだけです。jqueryを使用して、data {__RequestVerificationToken:$( "input [name = __ RequestVerificationToken]")。val()}を介してデータオブジェクト内に追加できます
Anthony Mason

16

私は現在のプロジェクトでこの実際の問題を実装していました。私は、認証されたユーザーを必要とするすべてのajax-POSTに対してそれを行いました。

まず、jquery ajax呼び出しをフックして、あまり頻繁に繰り返さないようにすることにしました。このJavaScriptスニペットは、すべてのajax(post)呼び出しがリクエスト検証トークンをリクエストに追加することを保証します。注:__RequestVerificationTokenという名前は.Netフレームワークで使用されるため、以下に示すように、標準のCSRF防止機能を利用できます。

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

上記のJavaScriptでトークンを使用できるようにするビューでは、一般的なHTMLヘルパーを使用するだけです。基本的に、このコードはどこにでも追加できます。私は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 Anti-CSRFメカニズムを使用するだけです。私はそれをこのようにしました(私は実際にソルトを使用しました)。

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

Firebugまたは同様のツールを使用すると、POSTリクエストに__RequestVerificationTokenパラメータが追加されている様子を簡単に確認できます。


15

「__RequestVerificationToken」入力がPOSTリクエストに含まれていることを確認するだけでよいと思います。情報の残りの半分(つまり、ユーザーのCookie内のトークン)は、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
MVC(Razor)ページ内からjQuery AJAX投稿を何時間も実験した後、これは私にとって有効なすべての最も簡単な答えでした。トークンの後に新しいデータとして(ただし、元のデータオブジェクト内に)独自のデータフィールド(または私が想定するviewModel)を含めるだけです。
ラルフベーコン

AJAX関数がRazorページではなく.htmlページにある場合、これをどのように実装しますか?
Bob the Builder

あなたのhtmlページにサーバーが提供されAntiForgeryTokenていない場合は、とにかくそれはすべて愚かです。動作する場合(その場合、どのように取得するかは不明ですが、そうであると想定)、上記はうまく機能します。上記のトークンを期待してサーバーにリクエストを送信する単純なWebページを作成しようとしていて、サーバーがそのページを生成しなかった場合は、うまくいきません。それが本質的にAntiForgeryTokenのポイントです...
jball 14

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とRazorを使用していて、jQuery AJAXを使用してフォームを送信しているため、一部のビューを新しい結果で更新でき、完全なポストバック(およびページフリッカー)を実行したくありませんでした。

追加 @Html.AntiForgeryToken()通常どおりフォーム中にます。

私のAJAX送信ボタンコード(つまり、onclickイベント)は次のとおりです。

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

私はフォーム全体のデータをモデルとしてPOSTするのが好きではないことを認めなければなりませんが、必要な場合は、これが機能する1つの方法です。MVCはデータバインディングを非常に簡単にするので、16個の個別の値(または弱い型指定のFormCollection)を送信するのではなく、これは問題ないと思います。あなたがよりよく知っているなら、私が堅牢なMVC C#コードを作りたいので私に知らせてください。


4

$ .ajaxの呼び出しごとにhttps://gist.github.com/scottrippey/3428114からこの非常に賢いアイデアを見つけ、リクエストを変更してトークンを追加しました。

// 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) {、コンテンツタイプを指定していないAjax呼び出しをキャッチするために追加する必要がありました
HostMyBus

3

1.サーバーからトークンを取得する関数を定義する

@function
{

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

2.サーバーに送信する前にトークンを取得してヘッダーを設定する

var token = '@TokenHeaderValue()';    

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

3. Post / getを処理するメソッドのHttpRequestBaseのオンサーバー検証

        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

この質問が投稿されてからしばらく時間が経過していることは承知していますが、AntiForgeryTokenの使用法について説明し、使用の煩わしさを軽減する本当に役立つリソースを見つけました。また、AJAX呼び出しに偽造防止トークンを簡単に含めるためのjqueryプラグインも提供します。

ASP.NET MVCおよびAJAXの偽造防止リクエストレシピ

私はあまり貢献していませんが、多分誰かがそれを役に立つと思うでしょう。


その投稿は1マイルの長さです。きっと素晴らしいですがtl; dr
BritishDeveloper

1
それは主題をうまくカバーしているので、残念です。これは、機能の使用方法を説明するだけでなく、修正された問題について説明し、正しく使用する方法を理解するためのコンテキストを提供します。セキュリティに関しては、よく理解することが重要だと思います。
slawek 2012

2
それが重要であるならば、それを人々がそれを読むのを奨励するような方法で書かれるべきです;)
BritishDeveloper '30

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ソリューションのわずかな改善。これにより、JavaScript関数内に偽造防止トークンが組み込まれるため、@ 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ポストを使用して削除メソッドを実行しています(visjsタイムラインからのものである可能性が高いですが、それは関係ありません)。これは私がsisものです:

これは私の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

わかりました。ここにはたくさんの投稿があります。何日もGoogleを助けてくれたわけではありません。それでも、アプリ全体を最初から作成することはできませんでした。それから、Web.confgにこの小さなナゲットがあることに気付きました。

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

今、なぜそれを追加したのかわかりませんが、後で気づきましたが、デバッグモードでは無視され、プロダクションモードでは無視されます(IISのどこかにインストールされています)

私にとって解決策は2つのオプションの1つでした、なぜそれを追加したのか覚えていないので、他のものがそれに依存していないことを確信できません。 * .localLookup.net

多分それは多分それを助けません。私はそれが誰かを助けることを願っています


0

私が見つけた解決策はASPXではなくRazor用ですが、かなり差し支えない問題です。

AntiForgeryをリクエストに追加することで解決しました。HTMLヘルパーは、呼び出しでHTML IDを作成しません

@Html.AntiForgeryToken()

トークンをpostrequestに追加するために、jQueryを使用してAntiForgery IDを隠しフィールドに追加しました:

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

これにより、コントローラは[ValidateAntiForgeryToken]属性を含むリクエストを受け入れました。


-3

AntiforgeryTokenはまだ苦痛であり、上記の例のどれも私にとって一言一句うまくいきませんでした。そこには多すぎる。だから私はそれらをすべて組み合わせました。iircにぶら下がっているフォームの@ Html.AntiforgeryTokenが必要

そのように解決:

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

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

疑問がある場合は、$記号を追加してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.