如何在集成测试中绕过表单 post 上的防伪令牌验证

How to bypass antiforgery token validation on form post in integration tests

我有一个 ASP.NET 核心 2.2 MVC 应用程序,它公开了一个带有基本表单的登录页面 (username/password)。 controller action受AntiForgeryTokenAttribute保护,隐藏__RequestVerificationToken由MVC添加

我正在使用 TestServer 编写集成测试,我想发送表单并查看是否收到 302 状态代码,但找不到任何有效选项。

我评估的一个选项是执行 GET,提取 __RequestVerificationToken,然后将 tpoken 作为表单的一部分提交。但是,这不会起作用,因为我缺少 cookie(我相信)。 TestServer.CreateClient 不支持任何处理程序,所以我无法添加 cookie。

有没有办法测试这个?

谢谢!

所以需要做两件事:

  1. 在页面 GET 期间:从 Headers 中获取 cookie 并提取 __RequestVerification
  2. 提交表单时:在 Headers 中添加 cookie,并在模型中添加 __RequestVerification

1。得到

您可以使用以下方法提取令牌:

headers.FirstOrDefault(x => x.Key == "Set-Cookie").Value.First().Split(" ")[0];

// The cookie we are looking for is .AspNetCore.Antiforgery.<unique guid>=<unique guid>
var tokenCookie = cookieContent.Split("=");
var name = tokenCookie[0];
var value = tokenCookie[1];

您可以使用 Nuget 包 HtmlAgilityPack 提取 __RequestVerification 然后执行:

var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(htmlContent);
var tokenValue = htmlDoc.DocumentNode.SelectSingleNode("//input[@name='__RequestVerificationToken']")
                .Attributes.Where(x => x.Name == "value").Select(x => x.Value).First();

其中 htmlContentHttpResponse.Content.ReadAsStringAsync();

2。 POST

创建表单时,添加 __RequestVerification令牌:

new FormUrlEncodedContent(new List<KeyValuePair<string, string>>
{
    ... your stuff here
    new KeyValuePair<string, string>("__RequestVerificationToken", token)
        });
}

然后在发送请求时:

var request = new HttpRequestMessage(HttpMethod.Post, endPoint)
{ Content = form };

request.Headers.Add("Cookie", $"{cookie.Name}={cookie.Value}");

await client.SendAsync(request);

其中 clientHttpClient 使用 TestServer.CreateClient 创建的。

希望这对其他人有帮助!

为了更好地获取所需的标记和字段名称,而无需从页面中抓取 HTML,我写了一篇博客 post 以及关于如何使用的相同示例代码实现相同目标的应用部分:

  1. Blog post
  2. Sample code