如何将 cookie 添加到注入服务中使用的HttpClient
(示例(?我已经创建了一些服务ApiService
并且该服务HttpClient
就像教程中的CatalogService
一样注入。问题是,为了与外部 API 通信,我的服务和它的HttpClient
必须有一个令牌,该令牌之前由另一个使用LoginService
的名为IdentityService
的 API 接收。因此,当登录在前面的 Web 应用程序中完成时:
if (!string.IsNullOrEmpty(user.Token)) {
ClaimsPrincipal principal = ValidateToken(user.Token);
if (principal != null) {
AuthenticationProperties p = new AuthenticationProperties();
p.ExpiresUtc = DateTime.UtcNow.AddDays(7);
p.IsPersistent = Persistant;
p.RedirectUri = Request.Query.ContainsKey("ReturnUrl") ? Request.Query["ReturnUrl"].ToString() : "";
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, p);
// those cookies are lost when ApiController is called - new instance of http client replaces this one
var apiService = HttpContext.RequestServices.GetService(typeof(IApiService));
var s = apiService as ApiService;
s.SetClientCookies("token", user.Token);
return new RedirectToPageResult("../Index");
}
}
return BadRequest("Invalid token");
SetClientCookies
目前看起来像这样,但它不起作用,因为 ApiService 构造函数获得了 HttpClient 的新实例:
public class ApiService: IApiService {
public static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
private HttpClient _client;
static string BaseUrl = "https://localhost:44365/api";
public ApiService(HttpClient client) {
_client = client;
}
public async Task < List < DbTest >> GetAccounts() {
var httpResponse = await _client.GetAsync(BaseUrl + "/account");
if (!httpResponse.IsSuccessStatusCode) {
throw new Exception("Cannot retrieve login");
}
var content = await httpResponse.Content.ReadAsStringAsync();
var accounts = JsonConvert.DeserializeObject < List < DbTest >> (content);
return accounts;
}
public void SetClientCookies(string key, string value) {
_client.DefaultRequestHeaders.Add("Cookie", key + "=" + value);
}
}
结果是,当 API 被调用时HttpClient
,没有"令牌"cookie...知道如何更改它以使ApiService
的HttpClient
不会丢失登录时收到的cookie吗?
相关Startup.cs
代码如下:
services.AddHttpClient<ILoginService, LoginService>("identityServiceClient");
services.AddHttpClient<IApiService, ApiService>("apiServiceClient")
.ConfigureHttpClient(client => {
client.Timeout = TimeSpan.FromSeconds(30);
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() {
CookieContainer = new CookieContainer()
});
一种可能性是将 cookie 容器添加到服务集合中
var container = new CookieContainer();
services.AddSingleton(container);
并在注册客户端时使用该实例
services.AddHttpClient<IApiService, ApiService>(client => {
client.Timeout = TimeSpan.FromSeconds(30);
client.BaseAddress = new Uri("https://localhost:44365/api").
}).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() {
CookieContainer = container,
UseCookies = true
});
现在,可以根据需要解析和操作容器。
var container = HttpContext.RequestServices.GetService<CookieContainer>();
container.Add(BaseUrl, new Cookie("token", user.Token));