2017-07-22 38 views
0

コアmvc​​プロジェクトで偽造防止機能を有効にしようとしましたが、運がありません。実行されたこと:ASP.NETコアMVC偽造防止

POST要求ごとに自動的に反偽造トークンをチェックするようにフィルタが追加されました。

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

このように各ページにトークンの生成が追加されました。

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery; 
@{ 
    var antiforgeryRequestToken = Antiforgery.GetAndStoreTokens(Context).RequestToken; 
} 
... 
... 
<script> 
    var antiforgeryToken = @Json.Serialize(antiforgeryRequestToken); 
</script> 

最後に、各クライアントのajaxリクエストは、このようにRequestVerificationTokenを追加します。

var options = { 
     url: o.url, type: 'POST', data: o.params, headers: { 'RequestVerificationToken': antiforgeryToken } }; 

各Ajaxリクエストにトークンがあるのがわかりますが、私はいつもPOSTリクエストで400を得ています。フィルタを無効にすると、正常に動作します。しかし、私はそれを有効にすると、asp.netコアはPOST要求ごとに検証を開始し、それは常に私に400を返します。

アイデア?

UPDATE:

私はコメントで得た指示に従ってきたし、今のコードは次のようになります。 ConfigureServices方法:

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

services.AddAntiforgery(o => o.CookieName = "XSRF-TOKEN"); 

そして、ここでは、登録されたミドルウェアです:

app.Use(next => context => { 
if (context.Request.Path == "/") 
{ 
    var antiforgery = app.ApplicationServices.GetService<IAntiforgery>(); 
    var token = antiforgery.GetAndStoreTokens(context); 
    context.Response.Cookies.Append("XSRF-TOKEN", token.RequestToken, new CookieOptions {HttpOnly = false}); 
} 

return next(context); 
}); 

私はまた、任意のクライアント側に前のヘッダを送信されたJavaScriptコードを削除しました。しかし、それはまだ動作しません。

+0

これは 'data:{__RequestVerificationToken:antiforgeryToken}'である必要があります。 – tchelidze

+0

ヘッダー名を 'RequestVerificationToken'から' __RequestVerificationToken'に変更する必要がありますか? –

+0

だけでなく、トークンは 'data'になければなりません。それがうまくいくか試してみてください。 – tchelidze

答えて

2

あなたは近くにいると思うよりはるかに簡単です。

最初に、services.AddMvc();を使用すると、偽造防止剤が既に追加されています。フィルタを追加する必要はありませんので、フィルタを削除してください。

次に、偽造防止構成を変更する必要があります。

// Old 
services.AddAntiforgery(o => o.CookieName = "XSRF-TOKEN"); 
// New 
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN"); 

これは、ajaxを使用している場合にのみ必要です。デフォルトでは、偽造防止システムはフォームデータのみを考慮します。

次に、@Html.AntiForgeryToken()を使用して、偽造防止トークンを簡単に生成できます。余分なコードは必要ありません。あなたはそれを取り除くことができます。これによりトークンの値が隠された<input />が作成されます。 asp-actionasp-controllerなどのタグヘルパーを使用している場合、<form />を使用している場合は、自動的に作成されます。これらのタグヘルパーを使用しない場合は、asp-antiforgery="true"を使用してください。

これで、あなたのajaxリクエストは、隠された<input />値を消費する可能性があります。ここに例があります:

$.ajax({ 
    method: "POST", 
    url: "/api/test", 
    data: data, 
    beforeSend: function (xhr) { 
     xhr.setRequestHeader("XSRF-TOKEN", 
      $('input:hidden[name="__RequestVerificationToken"]').val()); 
    }, 
    statusCode: { 
     200: function() { 
      alert("Success"); 
     }, 
     400: function() { 
      alert("Client error"); 
     }, 
     500: function() { 
      alert("Server error"); 
     } 
    } 
}); 

重要な部分はbeforeSendです。ここでは、リクエストヘッダーをセットアップ時に同じヘッダー名に設定します。Startup.cs

これで、必要な方法に[ValidateAntiForgeryToken]を追加するだけです。

最後に、テストする前に、追加したミドルウェアを削除してください。

これは1つの方法です。公式文書hereには他にも多くの解決策があります。 enter image description here

あなたのantiforgery設定オプションでこれを変更することができます。

+0

詳細な対応をありがとうございます。要点は、共有ビューでマークアップにトークンの生成があることです。私たちにはSPAアプリケーションがあり、ユーザーがサインインした後に共有ビューが再ロードされないため、手動で再生成する必要があります。あなたのアプローチを使用すると、ユーザーがサインインする前に入力フィールドに古いトークン値が生成されます。 –

+0

ああ、これはSPAアプリですか?手前で知ってよかったでしょうか。しかし、心配はありません。 Angular、React、Vueなどを使用していますか? –

+0

はい、これはSPAです。 –

0

は、両方のクッキーが同じパスを持っていることを確認してください。 fetchを使用して呼び出しを行う場合は、資格情報ヘッダーを含むCookieを送信していることを確認してください。

関連する問題