ASP.NET Core HttpClient For Antiforgery

2024-07-19

筆記 ASP.NET Core 如何對有 AntiForgery 的網站進行 POST 操作。

logo

說明

Post 的重點:

  • 要使用 UseDefaultCredentials = true 來使用 Windows 認證
  • 加入 User-Agent 來模擬瀏覽器連線
  • 使用 FormUrlEncodedContent 來傳送表單資料及
  • 要包含 Cookie ,透過 DefaultRequestHeaders.Add("Cookie", "key=value") 設定

其中針對 Antiforgery 的處理,需要加在 FormUrlEncodedContent 中,並且在 Cookie 中加入 __RequestVerificationToken 的值。

using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .Build();

var handler = new HttpClientHandler()
{
    UseDefaultCredentials = true
};

using (var client = new HttpClient(handler))
{
    client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0");

    // load url from appsettings.json
    var requestUri = configuration["Url"];

    var payload = new Dictionary<string, string>
    {
        { "__RequestVerificationToken", configuration["RequestVerificationToken"]! },
        { "Name", DateTime.Now.ToString() },
        { "ReserveDate", "2024-07-17T10:58" }
    };

    var cookies = new Dictionary<string, string>
    {
        {"__RequestVerificationToken", configuration["Cookie_RequestVerificationToken"]! }
    };
    
    // cookies for client
    foreach (var cookie in cookies)
    {
        client.DefaultRequestHeaders.Add("Cookie", $"{cookie.Key}={cookie.Value}");
    }

    while (true)
    {
        var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
        request.Content = new FormUrlEncodedContent(payload);

        var response = await client.SendAsync(request);
        //response.EnsureSuccessStatusCode();

        var responseBody = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseBody);
        Thread.Sleep(500);
    }
}
{
  "RequestVerificationToken": "0LmfCm9oFkX01",
  "Url": "https://localhost:44347/Reserves/Create",
  "Cookie_RequestVerificationToken": "bXSJUHahvaIRdsgY1"
}

搭配的 Controller 如下:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,ReserveDate")] Reserve reserve)
{
    string key = System.Configuration.ConfigurationManager.AppSettings["open"];
    if (key == "false")
    {
        return Content("System is closed");
    }

    if (ModelState.IsValid)
    {
        db.Reserve.Add(reserve);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(reserve);
}