2

我有一个 WPF(我猜可能是任何 winform)应用程序,它尝试使用HttpClient登录到标准 MVC 5 网站。

通常我可以通过调用PostAsync()成功登录,我在HttpContent中提供 UserName 和 Password 参数!

但是,当我将[ValidateAntiForgeryToken]添加到控制器的登录 (POST) 操作时,PostAsync() 调用失败并出现内部服务器错误。

我尝试从一个简单的 GET 请求中收集“__RequestVerificationToken”,并通过将其添加到 POST 参数、请求的标头或 HttpHandler 的CookieContainer(或三者的任意组合)与我的 POST 请求一起发送,但我仍然收到错误500 来自服务器。

我知道它可以用 HttpWebRequests 来完成(显然),但我不知道在使用 HttpClient 时我缺少什么。我也不知道服务器端到底出了什么问题..或者如何检查,因为代码永远不会到达我的控制器方法。

有没有其他人尝试过这个?

编辑 1

我正在为 GET 和 POST添加浏览器发送的原始数据:

GET http://localhost:57457/Account/Login HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://localhost:57457/Account/Login
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
DNT: 1
Host: localhost:57457
Cookie: NavigationTreeViewState=%5b%7b%27N0_1%27%3a%27T%27%2c%27N0%27%3a%27T%27%7d%2c%27N0_1_2%27%2c%7b%7d%5d; style=default; __RequestVerificationToken=Bak42Ga5sHJitYlmut6OgvmqXNmP7kKQRNaMSsLMAUh86iHGGmz5pnNfz_soKu46Wax9sG23arPOTnSh1bvaWyWqQ9NH4GJxFmendW8VFTg1

RESPONSE:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.2
X-Frame-Options: SAMEORIGIN
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRUJTLkNvZGVcUHJvamVjdHNcQ1ZSUE9TX1dlYlNpdGVcQ1ZSUE9TX1dlYlNpdGVcQWNjb3VudFxMb2dpbg==?=
X-Powered-By: ASP.NET
Date: Thu, 04 Dec 2014 10:00:00 GMT
Content-Length: 1734
[View page content]

POST http://localhost:57457/Account/Login HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://localhost:57457/Account/Login
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Content-Length: 180
DNT: 1
Host: localhost:57457
Pragma: no-cache
Cookie: NavigationTreeViewState=%5b%7b%27N0_1%27%3a%27T%27%2c%27N0%27%3a%27T%27%7d%2c%27N0_1_2%27%2c%7b%7d%5d; style=default; __RequestVerificationToken=Bak42Ga5sHJitYlmut6OgvmqXNmP7kKQRNaMSsLMAUh86iHGGmz5pnNfz_soKu46Wax9sG23arPOTnSh1bvaWyWqQ9NH4GJxFmendW8VFTg1

__RequestVerificationToken=Bak42Ga5sHJitYlmut6OgvmqXNmP7kKQRNaMSsLMAUh86iHGGmz5pnNfz_soKu46Wax9sG23arPOTnSh1bvaWyWqQ9NH4GJxFmendW8VFTg1&UserName=test&Password=test

RESPONSE:
HTTP/1.1 400 Bad request (user/password for testing purposes only)
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 5.2
X-Frame-Options: SAMEORIGIN
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?RDpcRUJTLkNvZGVcUHJvamVjdHNcQ1ZSUE9TX1dlYlNpdGVcQ1ZSUE9TX1dlYlNpdGVcQWNjb3VudFxMb2dpbg==?=
X-Powered-By: ASP.NET
Date: Thu, 04 Dec 2014 10:00:00 GMT
Content-Length: 4434
[View page content]

编辑 2

这是我的应用为 GET 和 POST 发送的内容:

GET http://localhost:57457/Account/Login HTTP/1.1
Host: localhost:57457
Connection: Keep-Alive

POST http://localhost:57457/Account/Login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: localhost:57457
Cookie: __RequestVerificationToken=df9nBSP_J1IiLrv84RwrkmvbYBrnH4iqv97wRvz6HMPLWBhgI4XzGeAFcschovHwD8mTtHU6xrmVxz1Ku96_BaoB79le_vLTcrgGemU4gjc1
Content-Length: 163
Expect: 100-continue

__RequestVerificationToken=df9nBSP_J1IiLrv84RwrkmvbYBrnH4iqv97wRvz6HMPLWBhgI4XzGeAFcschovHwD8mTtHU6xrmVxz1Ku96_BaoB79le_vLTcrgGemU4gjc1&UserName=test&Password=test

最后这是错误:

[HttpAntiForgeryException (0x80004005):验证提供的防伪令牌失败。cookie "__RequestVerificationToken" 和表单字段 "__RequestVerificationToken" 已交换。]

谢谢!

4

2 回答 2

3

您可能需要在请求中包含 aspnet session id cookie

编辑:好吧,这不是会话 ID,但您需要两个令牌才能发送回您的发布操作。

我认为您做错的事情是对两个令牌使用相同的值,但它们应该不同,尽管两个令牌的名称都是 __RequestVerificationToken。从 cookie 中抓取的令牌应该作为 cookie 发送回来,从表单字段中抓取的令牌作为表单字段返回。

于 2014-12-03T18:16:33.700 回答
1

HtmlHelper.AntiForgeryToken()这是因为您在应用程序的 POST 中缺少防伪令牌。

您需要HtmlHelper.AntiForgeryToken()在视图上从 WPF 应用程序加载页面。然后获取带有名称的隐藏输入元素的值,__RequestVerificationToken并将其附加到您对服务器的登录 POST 请求中。

于 2014-12-03T20:31:39.030 回答