如何使用来自 IHttpClientFactory 的 HttpClient 将 cookie 添加到请求中
Posted
技术标签:
【中文标题】如何使用来自 IHttpClientFactory 的 HttpClient 将 cookie 添加到请求中【英文标题】:How to add a cookie to a request using HttpClient from IHttpClientFactory 【发布时间】:2020-07-01 14:04:15 【问题描述】:背景
我正在开发一个 ASP.NET Core Web API,我们在 API 中调用第 3 方 API。这个第 3 方 API 要求每个请求都包含一个带有访问令牌的 cookie。我们的 API 从声明中获取此令牌(来自与请求关联的用户的 ClaimsPrincipal
)。
详细信息This answer 展示了如何在请求中设置 cookie,但该示例要求手动构造 HttpClient
(以便能够注入 HttpClientHandler
与CookieContainer
)。而且由于不希望手动实例化 HttpClient
,我宁愿通过 DI 注入 HttpClient
,this example 说明了这一点(使用 IHttpClientFactory
)。
在我的服务中,我可以访问一个注入的HttpClient
实例(_httpClient
),最简单的函数如下所示:
public async Task<string> GetStatusAsync(ClaimsPrincipal user)
// TODO: Add cookie with access token (from user's claims) before making request
return await _httpClient.GetStringAsync(Endpoints.Status);
This GitHub issue 询问在使用 IHttpClientFactory 时如何包含授权 cookie,答案是 use the header propagation middleware。现在谈谈我的问题:
据我所知,您在应用程序启动时的服务配置期间设置了标头传播中间件(包含所有标头和 cookie 等)。然而,在我们的 API 中,在实际向 3rd 方 API 发出请求之前,我没有身份验证 cookie 的值。
问题
在发出实际请求之前,如何在使用IHttpClientFactory
注入我的服务的HttpClient
实例上的请求中添加cookie?
【问题讨论】:
您可以在设置 HttpClientFactory 时使用ConfigurePrimaryHttpMessageHandler()
方法来配置主处理程序,这应该允许您使用 Cookie
类使用 HttpClientHandler
配置 cookie。 docs.microsoft.com/en-us/dotnet/api/…
【参考方案1】:
您可以在 AddHeaderPropagation 配置函数中放置一个静态函数:
services.AddHeaderPropagation(options =>
options.Headers.Add(MyCookie());
);
在MyCookie
函数内部,
从它们中获取当前上下文结束提取所有需要的数据。
如果您需要当前流程或当前控制器中的某些内容,您可以添加它
在 httpSession 中并将其放入 MyCookie
函数中。
【讨论】:
感谢您的回复。解决方案是使用标头传播,但使用当前上下文(可通过Headers.Add
重载之一获得),如下所示:***.com/a/62696725/310001【参考方案2】:
解决方案确实是使用header propagation。我只需要将所有部分正确地组合在一起即可。
标头传播在ConfigureServices
(在Startup.cs
)内配置。而且由于我想使用当前用户声明中的数据,所以诀窍是,在添加 cookie 标头时,使用一个重载,该重载接受一个函数,使您可以访问当前上下文:
services.AddHeaderPropagation(options =>
options.Headers.Add("Cookie", context =>
var accessToken = context.HttpContext.User.Claims.FirstOrDefault(c => c.Type == "access-token")?.Value;
return accessToken != null ? new StringValues($"token=accessToken") : new StringValues();
);
);
除此之外,由于我使用的是Typed Service,因此我还必须配置该特定服务应该转发 cookie 标头(在 Startup.cs
中的 ConfigureServices
内的同一位置):
services.AddHttpClient<IApiService, ApiService>(httpClient =>
httpClient.BaseAddress = new Uri("https://httpbin.org/");
).AddHeaderPropagation(options =>
options.Headers.Add("Cookie");
);
最后,给我带来了一些麻烦的事情:由于我使用的是当前用户声称的数据,因此注册了标头传播中间件(Configure
中的Configure
中的Startup.cs
)必须在添加身份验证中间件 (app.UseAuthentication();
) 之后发生。如果没有,则声明尚未设置。
作为最后的提示:在处理此问题时,我会在 https://httpbin.org/ 中领导我们。那里的请求检查端点对于查看您在请求中实际传递的数据非常有用。
【讨论】:
以上是关于如何使用来自 IHttpClientFactory 的 HttpClient 将 cookie 添加到请求中的主要内容,如果未能解决你的问题,请参考以下文章
如何在ASP.NET Core 中使用IHttpClientFactory
如何使用 Moq 从 IHttpClientFactory 模拟 HTTPClient 并结合 .NET Core 中的 Polly 策略
单元测试 | 如何Mock IHttpClientFactory