HttpClient 正在从其他请求的响应中发送请求 cookie

pet*_*low 6 c# cookies dotnet-httpclient asp.net-core

我们有一个 Web API (.NET Core 5),它将请求传递到另一个远程 Web API。

Web API 从传入请求中获取一些 cookie,并将它们附加到传出请求中。

通常情况下,这工作正常,我们会看到请求 cookie 到达远程 Web API。

但是,当同时发送多个请求时,一个传入请求的 cookie 会以某种方式泄漏到另一个请求的传出请求中

当使用完全独立的用户和完全独立的浏览器时,甚至会发生这种情况。

我尝试过并确认过的事情:

  • 将 cookie 从传入请求复制到传出请求的代码工作得很好。事实上,即使远程 API 上出现的 cookie 被“泄露”,我的自定义日志记录表明它仍然按预期工作

  • 我可以在远程 Web API 上(在其原始 IIS 日志中)看到预期/泄漏的请求 cookie,因此不可能是远程 API 将其添加到其管道中的请求中。

  • 添加了对 HttpClient 调用的日志记录,但看不到正在发送的意外 cookie。

  • 这在本地不会发生

  • 我的感觉是 HttpClient 中发生了一些事情?

  • 更新 1我添加了日志记录CopyCookieHandler,它只创建一次并被所有请求重用

  • 更新2我刚刚读到HttpMessageHandler实例导致CookieContainer对象被共享...这可能可以解释这一点... https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore -5.0#cookies 饼干

第一个 API 具有使用 HttpClient 的设置:

services.AddHttpContextAccessor()
services.AddHttpClient<IRemoteService, RemoteService>()
                .AddHttpMessageHandler<CopyCookieHandler>();
services.AddTransient<CopyCookieHandler>();
Run Code Online (Sandbox Code Playgroud)

在哪里

public class RemoteService : IRemoteService
{
   private HttpClient _client;
   public RemoteService(HttpClient client)
   {
      _client = client;
   }

   public async Task Get()
   {
      var request = new HttpRequestMessage("POST", "http://example.com");
      await MakeCall(request);
   }
}
Run Code Online (Sandbox Code Playgroud)

CopyCookieHandler

public class CopyCookieHandler : DelegatingHandler
{
  public IHttpContextAccessor _context;
  public CopyCookieHandler(IHttpContextAccessor context)
  {
     _context = context;
  }

  protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  {
     //Copies the incoming request cookie and adds to the outgoing request
     var productId = _context.HttpContext.Request.Cookies["productId"];
     request.Headers.Add(HeaderNames.Cookie, $"productId={productId});

     var response = await base.SendAsync(request, cancellationToken);
     return response;
  }
}

Run Code Online (Sandbox Code Playgroud)

pet*_*low 3

事实证明,默认情况下,HttpClientHandler会将响应 cookie 存储在 a 中CookieContainer,然后将它们附加到下一个请求中。

这解释了为什么我在远程 API 的请求上看到额外的 cookie,但它们实际上来自先前完成的请求的响应。

该文档引导我解决了这个问题

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0#cookies-1

ASP.NET Core 文档:HttpClient 和 Cookie

所以通过添加这段代码:

services.AddHttpClient<IRemoteService, RemoteService>()
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new HttpClientHandler()
        {
            UseCookies = false,
        };
    })
    .AddHttpMessageHandler<CopyCookieHandler>();
Run Code Online (Sandbox Code Playgroud)

将阻止HttpClientHandler在您的 请求之间共享您的 cookie HttpClient