web-dev-qa-db-ja.com

AJAXフォームのないValidateAntiForgeryTokenをMVCアクションメソッドにポストする

私はSOでこれを行う方法の例を見てきましたが、私が知る限り、これまで成功しなかった見つけることができるすべての例を試しました。私は試しました一部の実装を私のシナリオに変更しましたが、これも今のところ失敗しています。

私のページの_layout.cshtmlにこれがあるので、常にトークンを利用できます。

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

JavaScript utilsファイルにもこのメソッドがあります。

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

これはすべて期待どおりに機能しており、偽造防止トークンを取得しています。私の実際の投稿コードは:

_myPage.saveData = function() {
    var saveUrl = '/exercises/PostData';

    var myData = JSON.stringify(myPage.contextsArrays);

    $.ajax({
        type: 'POST',
        async: false,
        url: saveUrl,
        data: AddAntiForgeryToken({ myResults: myData }),
        success: function () {
            alert('saved');
        },
        dataType: 'json',
        contentType: "application/json; charset=utf-8"
    });
};
_

私のアクションメソッドは次のようになります。

_    [HttpPost, ValidateAntiForgeryToken, JsonExceptionFilter]
    public JsonResult PostData(List<ResultsDc> myResults)
    {
        return Json(_apiClient.SubmitResults(myResults));
    }
_

私はこれまでに試したさまざまな実装でこれをテストしてきましたが、応答は常に次のようになります。

_{"errorMessage":"The required anti-forgery form field \"__RequestVerificationToken\" is not present."}
_

私はフォームを投稿していません。それは単なるデータの配列ですが、実際に投稿されたデータをチェックすると、Jsonは正しく見えません(すべてエンコードされています)が、__ RequestVerificationTokenパラメータ名があり、トークン値も存在します。

私は現時点でこれにかなり混乱しており、MVCアクションが呼び出されるようにトークンを送信する正しい方法を見つけることができません。 ValidateAntiForgeryToken属性を削除し、データとしてJSON.stringify(myPage.contextsArrays);を指定すると、jsonは正しく(エンコードされていない)見え、正常にマッピングされます。

このトークンをフォームなしで適切に投稿するにはどうすればよいですか?

22
Jammer

Cardboard開発者が再びストライキを行います。

私がしなければならなかったすべては削除されました:

_contentType: "application/json; charset=utf-8"
_

そして、それによって(行われるポスト要求の種類が変わります)、実際のデータプロパティのJsonコンテンツを取得して、Tモデルタイプに正しくバインドしますDO NOTJSON.stringify()データ。

33
Jammer

(注:これは、すでにここにあるものとそれほど大きな違いはないことを知っています)

私はこれがすでに答えられていることを理解していますが、私はこれをかなりやっており、私の答えを山に追加します。私のサイトにはフォームがないので、これを処理する方法を考え出す必要がありました。 Stackoverflowに関する多くの調査といくつかのブログで、最終的に必要な情報が得られました。

まず、「マスター」ページ(MVC Razor)の上部にあるコードは次のとおりです。

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
    @Html.AntiForgeryToken()
}

次に、すべてのajax呼び出し(jQuery)で、次のように始めます。

var token = $("#__AjaxAntiForgeryForm input").val();
var dataObject = {
  __RequestVerificationToken: token,
  myData: "whatever"
};

$.ajax({
  url: '@Url.Action("action", "controller")',
  type: 'POST',
  dataType: 'json',
  data: dataObject,
  error: function (jqXHR, textStatus, errorThrown) {
    console.log("ERROR!");
  },
  success: function (data) {
    //whatever
  }
});

最後に、コントローラー側では、これは正常に機能します。

public class controllerController : Controller
{
    [HttpPost]
    [ValidateAntiForgeryToken]
    public JsonResult action (myModel myData)
    {
        return Json(new { Success = "true" }, JsonRequestBehavior.DenyGet);
    }
}

うまくいけば、これは同じボートの他の人を助けるでしょう。

15
ESDictor

検証は、フォームデータを参照するようにハードコードされています。

https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryTokenStore.cs

    public AntiForgeryToken GetFormToken(HttpContextBase httpContext)
    {
        string value = httpContext.Request.Form[_config.FormFieldName];

特定のフォーマットに従うことにより、フォーム送信をシミュレートできます。それについては、 POST request? でHTMLフォーム送信を模倣する方法を参照してください。

必要に応じて、独自のバリデーターを作成することもできます。 POST ValidateAntiForgeryToken を使用してAsp.Net MVC 2アプリにJSONデータを送信する方法)では、これを行う方法について説明しています。 MVC 2用ですが、そこからいくつかのアイデアをピックアップできます。

1
user247702