如何使用 IHttpClientFactory 中的 HttpClient 向请求添加 cookie
How to add a cookie to a request using HttpClient from IHttpClientFactory
背景
我正在开发一个 ASP.NET 核心 Web API,我们在 API 中称之为第 3 方 API。这个第 3 方 API 要求每个请求都包含一个带有访问令牌的 cookie。我们的 API 从声明中获取此令牌(来自与请求关联的用户的 ClaimsPrincipal
)。
详情
This answer shows how to set a cookie on a request, but the example requires that one manually constructs the HttpClient
(to be able to inject a HttpClientHandler
with a CookieContainer
). And since it is not desirable to do manual instantiation of the HttpClient
, I would rather get the HttpClient
injected through DI, which 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 asks about how to include authorization cookie when using IHttpClientFactory, and the answer says to use the header propagation middleware。现在谈谈我的问题:
据我所知,您在应用程序启动时的服务配置期间设置了 header 传播中间件(包括所有 header 和 cookie 等等)。然而,在我们的 API 中,在实际向第三方 API.
发出请求之前,我没有身份验证 cookie 的值
问题
如何在发出实际请求之前向使用 IHttpClientFactory
注入我的服务的 HttpClient
实例的请求添加 cookie?
您可以在 AddHeaderPropagation 配置函数中放置一个静态函数:
services.AddHeaderPropagation(options =>
{
options.Headers.Add(MyCookie());
});
在 MyCookie
函数中,
获取当前上下文并从中提取所有需要的数据。
如果您需要当前流程或当前控制器中的某些内容,您可以添加它
在 httpSession 中并将其放入 MyCookie
函数中。
解决方案确实是使用 header propagation。我只需要将所有的部分正确地组合在一起即可。
Header 传播配置在 ConfigureServices
内部(在 Startup.cs
中)。因为我想使用来自当前用户声明的数据,所以诀窍是,在添加 cookie header 时,使用一个重载,该重载接受一个函数,使您可以访问当前上下文:
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 header(在 [=12= 内的同一位置) ] 在 Startup.cs
):
services.AddHttpClient<IApiService, ApiService>(httpClient =>
{
httpClient.BaseAddress = new Uri("https://httpbin.org/");
}).AddHeaderPropagation(options =>
{
options.Headers.Add("Cookie");
});
最后,给我带来了一些麻烦:由于我使用的是当前用户声明的数据,header 传播中间件的注册(app.UseHeaderPropagation();
里面Startup.cs
中的 Configure
) 必须在 添加身份验证中间件 (app.UseAuthentication();
) 之后发生 。如果没有,则声明尚未设置。
作为最后的提示:我在 https://httpbin.org/ 工作时领导我们。那里的请求检查端点对于查看您在请求中实际传递的数据非常有用。
背景
我正在开发一个 ASP.NET 核心 Web API,我们在 API 中称之为第 3 方 API。这个第 3 方 API 要求每个请求都包含一个带有访问令牌的 cookie。我们的 API 从声明中获取此令牌(来自与请求关联的用户的 ClaimsPrincipal
)。
详情
This answer shows how to set a cookie on a request, but the example requires that one manually constructs the HttpClient
(to be able to inject a HttpClientHandler
with a CookieContainer
). And since it is not desirable to do manual instantiation of the HttpClient
, I would rather get the HttpClient
injected through DI, which 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 asks about how to include authorization cookie when using IHttpClientFactory, and the answer says to use the header propagation middleware。现在谈谈我的问题:
据我所知,您在应用程序启动时的服务配置期间设置了 header 传播中间件(包括所有 header 和 cookie 等等)。然而,在我们的 API 中,在实际向第三方 API.
发出请求之前,我没有身份验证 cookie 的值问题
如何在发出实际请求之前向使用 IHttpClientFactory
注入我的服务的 HttpClient
实例的请求添加 cookie?
您可以在 AddHeaderPropagation 配置函数中放置一个静态函数:
services.AddHeaderPropagation(options =>
{
options.Headers.Add(MyCookie());
});
在 MyCookie
函数中,
获取当前上下文并从中提取所有需要的数据。
如果您需要当前流程或当前控制器中的某些内容,您可以添加它
在 httpSession 中并将其放入 MyCookie
函数中。
解决方案确实是使用 header propagation。我只需要将所有的部分正确地组合在一起即可。
Header 传播配置在 ConfigureServices
内部(在 Startup.cs
中)。因为我想使用来自当前用户声明的数据,所以诀窍是,在添加 cookie header 时,使用一个重载,该重载接受一个函数,使您可以访问当前上下文:
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 header(在 [=12= 内的同一位置) ] 在 Startup.cs
):
services.AddHttpClient<IApiService, ApiService>(httpClient =>
{
httpClient.BaseAddress = new Uri("https://httpbin.org/");
}).AddHeaderPropagation(options =>
{
options.Headers.Add("Cookie");
});
最后,给我带来了一些麻烦:由于我使用的是当前用户声明的数据,header 传播中间件的注册(app.UseHeaderPropagation();
里面Startup.cs
中的 Configure
) 必须在 添加身份验证中间件 (app.UseAuthentication();
) 之后发生 。如果没有,则声明尚未设置。
作为最后的提示:我在 https://httpbin.org/ 工作时领导我们。那里的请求检查端点对于查看您在请求中实际传递的数据非常有用。