提供AntiForgery令牌与System.Net.Http.HttpClient和MVC
我有一个WPF(可能是任何winform我猜)尝试登录到标准的MVC 5网站使用HttpClient。提供AntiForgery令牌与System.Net.Http.HttpClient和MVC
Normally I can login successfully with a call to PostAsync() where I provide the UserName and Password params in a HttpContent!
然而,当我加入[ValidateAntiForgeryToken]到我的控制器的登录(POST)动作,PostAsync()调用失败,内部服务器错误。
我试图从一个简单的GET请求收集“__RequestVerificationToken”,并通过将其添加到POST参数,可以请求的报头或所述的HttpHandler的的CookieContainer(或三者的任意组合与我的POST请求发送它)但仍然从服务器收到错误500。
我知道这可以用HttpWebRequests(apparently)完成,但我不知道我在使用HttpClient时丢失了什么。我也不知道服务器端发生了什么错误,或者如何检查,因为代码永远不会达到我的控制器方法。
其他人试过这个吗?
EDIT 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 "被交换。]
谢谢!
你D可能需要包括ASPNET会话cookie您的要求
编辑: 确定你是对的,它不是会话ID,但你需要两个令牌传送回您的文章的行动。
我认为你做错了什么是两个令牌使用相同的值,但它们应该是不同的,这两个令牌的名称都是__RequestVerificationToken。 从cookie中抓取的令牌应该作为cookie返回,从表单字段中抓取的令牌将作为表单字段返回。
谢谢,但我不认为这种情况。这真的没有任何意义,除此之外,当我没有[ValidateAntiForgeryToken]登录时,我没有传递任何会话ID,它工作得很好。 – raptor 2014-12-03 18:40:06
据我所知,生成的伪造令牌绑定到会话值,出于安全原因停留在服务器上,所以请求令牌,然后在登录过程中进行验证,应该发生在同一会话中。 – 2014-12-03 21:51:32
就服务器而言,一切都发生在同一个会话中。话虽如此,我肯定怀疑会议与此有关(你可以从我的编辑看到浏览器正在使用什么数据/ cookies)的事实 – raptor 2014-12-03 22:38:28
这是因为您在应用程序中的POST中缺少来自HtmlHelper.AntiForgeryToken()
的反伪造令牌。
您需要在视图中从您的WPF应用程序加载HtmlHelper.AntiForgeryToken()
的页面。然后获取名称为__RequestVerificationToken
的隐藏输入元素的值,并将其附加到您对服务器的登录POST请求。
对不起,我从我的问题中忽略了这些信息,但我也尝试过:我发出了一个GET请求,将__RequestVerificationToken挖出并将其添加到所有我能想到的地方:后缀参数(模拟隐藏的浏览器字段),请求头(因为我看到浏览器也是这样做的)和cookie(因为我的第一个GET请求放在那里)。可悲的是,他们没有任何组合没有工作。 – raptor 2014-12-03 21:32:58
@raptor你有没有尝试过使用Fiddler来检查一个真正的登录请求,然后看看你的应用程序提交? – 2014-12-03 21:37:38
我很抱歉,但我不知道如何使用小提琴来监控应用程序。当我使用应用程序登录时,它不显示任何流量。现在,我向问题中添加了从浏览器获得的数据,我将研究如何(或者如果)我可以使用提琴手实际监控应用程序,并返回我的发现。 – raptor 2014-12-03 22:27:20
你也可以发布原始http响应 – 2014-12-04 09:47:26
只是标题btw – 2014-12-04 09:49:27