ChatGPT解决这个技术问题 Extra ChatGPT

在 .net 4.5 中尝试使用 HttpClient 使 cookie 无法响应

我有以下代码可以成功运行。我不知道如何从响应中获取 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;
}
出于好奇,我能问一下您为什么要在客户端读取cookie吗?我的理解是cookies用于向服务器发送信息,而不是用于返回信息。
我在返回 JSON 的调用中使用返回的 cookie,这样我就不必为每个 JSON 调用进行单独的授权调用。也就是说,我有一个调用日志 /Home/GetData ,它返回 JSON 但只有在授权的情况下。在客户端请求中,我添加了 cookie,以便 /Home/GetData 响应。否则它会说“403”未经授权。
将授权标头设置为默认标头几乎同样有效且更加标准。服务器无法代表客户端自动设置身份验证标头。
感谢达雷尔的提示。您是否有任何关于 asp.net 中的示例?我为我的 monotouch 和现在的 windows 商店应用程序而苦苦挣扎。如果有一个简单的方法,我会很高兴。这很痛苦,尤其是在 Windows 商店应用程序上使用 async 和 await now。

D
Despertar

要将 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会自动发送,无需额外步骤。
您必须添加“使用 System.linq;”
如果 httpclient 是从 httpclient 工厂构建的,是否可以以相同的方式获取 cookie?即添加到services.AddHttpClient的builder方法
在获取异步时,我们已经引用了“google.com”,为什么我们需要再次声明一个引用它的 URI?
@FireController1847,如果您想将其用作 IEnumerable,则只需进行转换,因为 GetCookies() 方法返回 CookieCollection,而不是 IEnumerable。如果您所做的只是使用上面代码中的循环,则 IMO 不需要强制转换,因为您仍然可以枚举 CookieCollection,因为它继承了 IEnumerable。
R
Rytis I

如果您无权访问 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 存在。
Set-Cookie 标头确实有多个值,它们用分号 (;) 分隔,但通常应该只有一个 Set-Cookie 标头
A
Alper Ebicoglu

您可以使用给定的 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;
        }
    }
}

D
Deivydas Voroneckis

并非在所有情况下都可以将 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 属性。


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅