前陣子介紹在 ASP.NET Core MVC 啟用 CSRF 防護的做法,今天說說實務上啟用後可能遇到的問題。

用上回說的 AJAX 呼叫範例示範,假設我們發現 JavaScript 送出的表單資料似乎有點問題,想用瀏覽器 F12 工具調查一下,結果...

來源頁籤顯示 Content unavailable. Resource was not cached.,完全看不到 HTML 及 JavaScript,無從偵錯起。

原因是 ASP.NET Core 的 AntiForgery 機制啟用時,會自動在回應 Header 加上 Cache-Control: no-cache, no-store,禁止瀏覽器快取網頁內容:

這個行為來自 IAntiforgery.GetAndStoreTokens(HttpContext),ASP.NET Core 將 Cookie 權杖儲存在回應的同時,會一併將 「Cache-control」 和 「Pragma」 標頭設定為 「no-cache」,並將 「X-Frame-Options」 標頭設定為 「SAMEORIGIN」(註:實測時未看到文件所說的 X-Frame-Options Header,網路上也有文章提到相同問題,推測是新版 ASP.NET Core 行為改變),降低防偽權杖被竊取的機率。

【2025-11-23 更新】

耍笨了,其實只要勾選網路頁籤「停用快取」就可解決囉。(感謝 Laneser 分享)

以下內容請全部忽略。

經過研究,有兩個解決方向:設法加入 MiddleWare 層取消 no-cache Header、允許在測試偵錯階段停用 AntiForgery,後者明顯簡單許多。我的解法是在 Program.cs 加入依據 builder.Configuration.GetValue<bool>("DisableAntiForgery") 決定是否停用 AntiForgery 檢查的邏輯:

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews(options =>
{
    if (!builder.Configuration.GetValue<bool>("DisableAntiForgery")) {
        options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
    }
});
var app = builder.Build();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

AJAX.cshtml 呼叫 @Html.AntiForgeryToken() 也會觸發寫入 no-cache,故 HomeController.cs 及 AJAX.cshtml 都要調整:

IConfiguration _config;
public HomeController(IConfiguration config)
{
    _config = config;
}

[HttpGet]
public IActionResult Ajax()
{
    ViewBag.DisableAntiForgery = _config.GetValue<bool>("DisableAntiForgery");
    return View();
}
@if (!(ViewBag.DisableAntiForgery ?? false)) {
    @Html.AntiForgeryToken()
}

如此,加上 --DisableAntiForgery=true 參數便可暫時停用 AntiFogery,順利 Debug 囉

Discusses ASP.NET Core’s CSRF protection causing “no-cache” headers, blocking browser debugging; shows how to temporarily disable AntiForgery for development.


Comments

# by Laneser

我記得在 DevTools 的 Network (網路) 標籤中,勾選頂部的 Disable cache (停用快取) 選項。 應該就可以了,不然要怎麼 debug 別人的網頁呢?!(當然也可以透過 overwrite response 的 no cache...)

# by Jeffrey

to Laneser,真的耶,耍笨了,謝謝分享密技。

Post a comment