在 .net 4.5 中尝试使用 HttpClient 使 cookie 无法响应
Posted
技术标签:
【中文标题】在 .net 4.5 中尝试使用 HttpClient 使 cookie 无法响应【英文标题】:Struggling trying to get cookie out of response with HttpClient in .net 4.5 【发布时间】:2012-11-10 00:48:17 【问题描述】:我有以下代码可以成功运行。我不知道如何从响应中获取 cookie。我的目标是我希望能够在请求中设置 cookie 并从响应中获取 cookie。想法?
private async Task<string> Login(string username, string password)
try
string url = "http://app.agelessemail.com/account/login/";
Uri address = new Uri(url);
var postData = new List<KeyValuePair<string, string>>
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password ", password)
;
HttpContent content = new FormUrlEncodedContent(postData);
var cookieJar = new CookieContainer();
var handler = new HttpClientHandler
CookieContainer = cookieJar,
UseCookies = true,
UseDefaultCredentials = false
;
var client = new HttpClient(handler)
BaseAddress = address
;
HttpResponseMessage response = await client.PostAsync(url,content);
response.EnsureSuccessStatusCode();
string body = await response.Content.ReadAsStringAsync();
return body;
catch (Exception e)
return e.ToString();
这是完整的答案:
HttpResponseMessage response = await client.PostAsync(url,content);
response.EnsureSuccessStatusCode();
Uri uri = new Uri(UrlBase);
var responseCookies = cookieJar.GetCookies(uri);
foreach (Cookie cookie in responseCookies)
string cookieName = cookie.Name;
string cookieValue = cookie.Value;
【问题讨论】:
出于好奇,请问您为什么要在客户端读取cookies?我的理解是cookies是用来向服务器发送信息的,不是用来返回信息的。 我在返回 JSON 的调用中使用返回的 cookie,这样我就不必为每个 JSON 调用进行单独的授权调用。也就是说,我有一个调用日志 /Home/GetData ,它返回 JSON 但只有在授权的情况下。在客户端请求中,我添加了 cookie,以便 /Home/GetData 响应。否则它会说“403”未授权。 将授权标头设置为默认标头几乎同样有效且更加标准。服务器无法代表客户端自动设置 auth 标头。 感谢达雷尔的提示。您是否有任何关于 asp.net 中的示例?我为我的 monotouch 和现在的 windows 商店应用程序而苦苦挣扎。如果有一个简单的方法,我会很高兴。这很痛苦,尤其是在 Windows 商店应用程序上使用 async 和 await now。 【参考方案1】:要将 cookie 添加到请求中,请在请求之前使用 CookieContainer.Add(uri, cookie)
填充 cookie 容器。发出请求后,cookie 容器将自动填充来自响应的所有 cookie。然后,您可以调用 GetCookies() 来检索它们。
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("http://google.com").Result;
Uri uri = new Uri("http://google.com");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
Console.WriteLine(cookie.Name + ": " + cookie.Value);
Console.ReadLine();
【讨论】:
注意:在第一次调用中收到初始cookies后,当访问同域的任何页面时,cookies会自动发送,无需额外步骤。 必须加上“using System.linq;” 如果httpclient
是从 httpclient 工厂构建的,是否有可能以相同的方式获取 cookie?即添加到 services.AddHttpClient 的构建器方法
在获取异步时我们已经引用了“google.com”,为什么我们需要再次声明一个引用它的URI?
@FireController1847 如果您想将其用作 IEnumerable如果您无权访问 HttpClient
并且无法注入 CookieContainer
,则可以选择其他方法。这适用于 .NET Core 2.2:
private string GetCookie(HttpResponseMessage message)
message.Headers.TryGetValues("Set-Cookie", out var setCookie);
var setCookieString = setCookie.Single();
var cookieTokens = setCookieString.Split(';');
var firstCookie = cookieTokens.FirstOrDefault();
var keyValueTokens = firstCookie.Split('=');
var valueString = keyValueTokens[1];
var cookieValue = HttpUtility.UrlDecode(valueString);
return cookieValue;
【讨论】:
刚刚试过这个,var setCookieString = setCookie.Single();
可能应该更改,因为setCookie
很可能有多个值,从而导致抛出异常。我最终添加了一个参数string cookieName
,然后使用了setCookie.Single(x => x.StartsWith(cookieName));
。这仍然假定请求的 cookie 存在。【参考方案3】:
您可以使用给定的 URL 轻松获取 cookie 值。
private async Task<string> GetCookieValue(string url, string cookieName)
var cookieContainer = new CookieContainer();
var uri = new Uri(url);
using (var httpClientHandler = new HttpClientHandler
CookieContainer = cookieContainer
)
using (var httpClient = new HttpClient(httpClientHandler))
await httpClient.GetAsync(uri);
var cookie = cookieContainer.GetCookies(uri).Cast<Cookie>().FirstOrDefault(x => x.Name == cookieName);
return cookie?.Value;
【讨论】:
【参考方案4】:并非在所有情况下都可以将httpClientHandler
添加到httpClient
。例如,当您使用集成测试testServer.CreateClient()
或从IHttpClientFactory
注入httpClient
时。所以,我只是从标题中读取值。
public static List<Cookie> GetCookies(this HttpResponseMessage message)
message.Headers.TryGetValues("Set-Cookie", out var cookiesHeader);
var cookies = cookiesHeader.Select(cookieString => CreateCookie(cookieString)).ToList();
return cookies;
private static Cookie CreateCookie(string cookieString)
var properties = cookieString.Split(';', StringSplitOptions.TrimEntries);
var name = properties[0].Split("=")[0];
var value = properties[0].Split("=")[1];
var path = properties[2].Replace("path=", "");
var cookie = new Cookie(name, value, path)
Secure = properties.Contains("secure"),
HttpOnly = properties.Contains("httponly"),
Expires = DateTime.Parse(properties[1].Replace("expires=", ""))
;
return cookie;
CreateCookie
方法可以修改为与您的 cookie 属性完全匹配。
【讨论】:
以上是关于在 .net 4.5 中尝试使用 HttpClient 使 cookie 无法响应的主要内容,如果未能解决你的问题,请参考以下文章
在 .Net 4.5 中使用 Websocket 的示例 [关闭]
.net 4.5 中可绑定的 WPF Richtextbox