.Net HttpClient 使用 Cookie

发布于:2025-05-15 ⋅ 阅读:(22) ⋅ 点赞:(0)

在 HttpClient 中使用 Cookie

Cookie 是服务器存储在客户端的小型数据片段,可用于身份验证、会话跟踪等。

.Net HttpClient 支持 Cookie 功能,本教程详细介绍了Cookie 的管理与使用。

初始化

#!import "./Ini.ipynb"

什么是 Cookie

Cookie 是服务器发送到用户浏览器并存储在本地的一小段数据,用来进行会话管理(如登录状态)、个性化设置(如主题偏好)、跟踪用户行为等功能。

HttClient 手动管理 Cookie

如果只在简单的使用Cookie,想保持简洁、灵活。可以手管理。

发送带Cookie的请求

  • 不使用Cookie
{   //不使用Cookie
    using (var client = new HttpClient(){BaseAddress=new Uri(webApiBaseUrl)})
    {
        var response = await client.GetAsync("/api/Cookie/GetRequestCookie"); 

        //确保请求成功
        response.EnsureSuccessStatusCode();

        //读取响应内容
        var content = await response.Content.ReadAsStringAsync();

        //输出 响应内容
        Console.WriteLine(content);
    }
}
  • 手动设置Cookie: 在默认请求头中添加Cookie,适合快捷请求方法(Get,Post,Put,Delete等)
{   //多次请求时,都自动携带默认请求头Cookie

    var client = new HttpClient()
    {
        BaseAddress = new Uri(webApiBaseUrl),
    };

    //全局设置Cookie,所有快捷请求(Send方法的快捷方法:Get、Post、Put等)都会带上这个Cookie
    //快捷方法,不能单独设置Cookie; 只有Send方法才可以单独设置Cookie
    client.DefaultRequestHeaders.Add("Cookie", "Client=PolyglotNotebook,User=andy");

    //请求1
    var response = await client.GetAsync("/api/Cookie/GetRequestCookie"); 

    //确保请求成功
    response.EnsureSuccessStatusCode();

    //读取响应内容
    var content = await response.Content.ReadAsStringAsync();

    //输出 响应内容
    Console.WriteLine(content);

    //再次快捷请求,不用重新设置
    //请求2
    var response2 = await client.GetAsync("/api/Cookie/GetRequestCookie"); 

    //确保请求成功
    response2.EnsureSuccessStatusCode();

    //读取响应内容
    var content2 = await response2.Content.ReadAsStringAsync();

    //输出 响应内容
    Console.WriteLine(content2);

}
  • 手动设置Cookie:每次请求设置 HttpRequestMessage,适合Send通用方法。当然可以合并默认请求头
{   //手动设置Cookie, 单次HttpRequestMessage合并默认请求头Cookie

    var client = new HttpClient()
    {
        BaseAddress = new Uri(webApiBaseUrl),
    };

    //全局设置Cookie,所有请求都会带上这个Cookie
    client.DefaultRequestHeaders.Add("Cookie", "Client=PolyglotNotebook,User=andy");

    //单请求设置
    var requestMessage = new HttpRequestMessage(HttpMethod.Get, "/api/Cookie/GetRequestCookie");
    
    //设置Cookie,会覆盖HttpClient设置的默认Cookie
    requestMessage.Headers.Add("Cookie", "Password=MyPassword,Role=Admin");
    //添加默认
    if(client.DefaultRequestHeaders.Contains("Cookie"))
    {
        requestMessage.Headers.Add("Cookie", client.DefaultRequestHeaders.GetValues("Cookie"));
    }

    var response = await client.SendAsync(requestMessage);
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(content);

    //响应头也会自动带上Cookie
    if(response.Headers.Contains("cookie"))
    {
        Console.Write($"响应头中Cookie为:");
        var cookies = response.Headers.GetValues("cookie");
        foreach (var cookie in cookies)
        {
            Console.WriteLine($"{cookie}");
        }
    }
    else
    {
        Console.WriteLine($"响应头中没有Cookie");
    }
}

查看响应头中的Cookie

{   //获取响应头中的Cookie

    var client = new HttpClient()
    {
        BaseAddress = new Uri(webApiBaseUrl),
    };

    var response = await client.GetAsync("/api/Cookie/GetResponseCookie");

    //获取响应头中的Cookie
    if(response.Headers.Contains("cookie"))
    {
        Console.Write($"响应头中Cookie为:");
        var cookies = response.Headers.GetValues("cookie");
        foreach (var cookie in cookies)
        {
            Console.WriteLine($"{cookie}");
        }
    }
    else
    {
        Console.WriteLine($"响应头中没有Cookie");
    }
}

HttClient 使用 CookieContainer 自动管理 Cookie

.NET 提供了 HttpClientHandler + CookieContainer 来自动管理 Cookie 生命周期和持久化。

使用 CookieContainer

{
    var handler = new HttpClientHandler()
    {
        UseCookies = true,
        CookieContainer = new CookieContainer(),
    };

    using var client = new HttpClient(handler)
    {
        BaseAddress = new Uri(webApiBaseUrl),
    };

    // 第一次请求,服务端设置 Cookie
    var response = await client.GetAsync("/api/Cookie/GetResponseCookie");
    response.EnsureSuccessStatusCode();

    // 第二次请求,自动携带之前设置的 Cookie
    var response2 = await client.GetAsync("/api/Cookie/GetRequestCookie");
    var content2 = await response2.Content.ReadAsStringAsync();
    Console.WriteLine(content2);
}

Cookie 持久化(保存与恢复)

若需要在程序重启后继续使用 Cookie,可将其序列化保存至文件或数据库。

  • 保存 Cookie 到文件
///<summary
/// 保存Cookie到文件
///</summary>
public void SaveCookies(CookieContainer container, string filePath)
{
    using (var writer = new StreamWriter(filePath))
    {
        foreach (Cookie cookie in container.GetCookies(new Uri(webApiBaseUrl)))
        {
            writer.WriteLine($"{cookie.Name}={cookie.Value};Domain={cookie.Domain};Path={cookie.Path};Expires={cookie.Expires}");
        }
    }
}

//应用
{
    var handler = new HttpClientHandler()
    {
        UseCookies = true,
        CookieContainer = new CookieContainer(),
    };

    using (var client = new HttpClient(handler))
    {
        client.BaseAddress = new Uri(webApiBaseUrl);

        // 第一次请求,服务端设置 Cookie
        var response = await client.GetAsync("/api/Cookie/GetResponseCookie");
        response.EnsureSuccessStatusCode();

        SaveCookies(handler.CookieContainer, "cookies.txt");
    }
}
  • 从文件中加载 Cookie
 <summary>
/// 从文件中加载 Cookie
/// </summary>
public CookieContainer LoadCookies(string filePath)
{
    var container = new CookieContainer();
    if (!File.Exists(filePath)) return container;

    foreach (var line in File.ReadAllLines(filePath))
    {
        var parts = line.Split(';');
        var nameValue = parts[0].Split('=');
        var cookie = new Cookie(nameValue[0], nameValue[1])
        {
            Domain = parts[1].Replace("Domain=", "").Trim(),
            Path = parts[2].Replace("Path=", "").Trim(),
            Expires = DateTime.Parse(parts[3].Replace("Expires=", "").Trim())
        };
        container.Add(cookie);
    }

    return container;
}

//发送请求:从文件中加载 Cookie, 在请求中携带
{
    var cookieBox = LoadCookies("cookies.txt");

    var handler = new HttpClientHandler()
    {
        UseCookies = true,
        CookieContainer = cookieBox,
    };

    var client = new HttpClient(handler)
    {
        BaseAddress = new Uri(webApiBaseUrl)
    };

    // 第一次请求,服务端设置 Cookie
    var response = await client.GetAsync("/api/Cookie/GetRequestCookie");
    response.EnsureSuccessStatusCode();

    var content = await response.Content.ReadAsStringAsync();

    Console.WriteLine(content);
}

跨域 Cookie 处理

默认情况下,CookieContainer 会根据域名自动隔离 Cookie。若需跨域共享 Cookie,可通过以下方式实现:

  • 手动复制 Cookie
//示例代码,无实际请求
var sourceUri = new Uri("https://source.com");
var targetUri = new Uri("https://target.com");

foreach (Cookie cookie in handler.CookieContainer.GetCookies(sourceUri))
{
    var crossDomainCookie = new Cookie(cookie.Name, cookie.Value, cookie.Path, targetUri.Host);
    handler.CookieContainer.Add(targetUri, crossDomainCookie);
}
  • 自定义 CookieContainer(高级)
    可以继承 CookieContainer 并重写相关方法以实现自定义 Cookie 共享策略。

进阶功能:Cookie 过期、安全标志、SameSite 设置等

  • 设置 Cookie 高级属性
{
    //发送请求
    {
        var handler = new HttpClientHandler()
        {
            UseCookies = true,
            CookieContainer = new CookieContainer(),
        };

        var client = new HttpClient(handler)
        {
            BaseAddress = new Uri(webApiBaseUrl)
        };

        //设置Cookie
        var cookie = new Cookie("jwt_token", "a.b.c")
        {
            Expires = DateTime.Now.AddDays(7),
            Domain = new Uri(webApiBaseUrl).Host,
            Path = "/",
            Secure = true,           // 仅 HTTPS 传输
            HttpOnly = true,         // 防止 XSS 攻击
        };

        handler.CookieContainer.Add(new Uri(webApiBaseUrl), cookie);

        // 第一次请求,服务端设置 Cookie
        var response = await client.GetAsync("/api/Cookie/GetRequestCookie");
        response.EnsureSuccessStatusCode();

        var content = await response.Content.ReadAsStringAsync();

        Console.WriteLine(content);
    }
}

总结

功能 描述 适用场景
手动设置 Cookie 灵活、简单 单次请求或固定 Cookie
使用 HttpRequestMessage 更精细控制 Cookie 行为 需要合并默认与自定义 Cookie
使用 CookieContainer 自动管理 Cookie 生命周期 多次请求、需要保持会话状态
Cookie 持久化 保存 Cookie 至文件或数据库 程序重启后仍需保持登录状态
跨域 Cookie 手动复制或自定义容器 需要在多个域名之间共享 Cookie
安全 Cookie 设置 SecureHttpOnlySameSite 增强 Cookie 安全性
获取 Cookie 属性 查看 Cookie 的有效期、路径等信息 调试和日志记录

网站公告

今日签到

点亮在社区的每一天
去签到