【问题标题】:Add cookies to dependancy injected HttpClient in Asp.Net Core在 Asp.Net Core 中添加 cookie 到依赖注入 HttpClient
【发布时间】:2020-01-11 00:27:21
【问题描述】:

如何将 cookie 添加到注入服务 (example) 中使用的 HttpClient?我创建了一些服务ApiService,并且该服务注入了HttpClient,就像教程中的CatalogService 一样。问题是,为了与外部 API 通信,我的服务和它的 HttpClient 必须有一个令牌,该令牌以前由另一个名为 IdentityService 的 API 使用 LoginService 接收。因此,当在前端 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);
    }
}

结果是,当使用HttpClient 调用 API 时,没有“令牌”cookie...知道如何更改它,以便ApiServiceHttpClient 不会丢失其接收到的 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()
    });

【问题讨论】:

  • 删除 HttpClient 并在您的构造函数中添加 «IHttpClientFactory factory»。然后调用«_client = clientFactory.CreateClient("apiServiceClient")»。我认为这应该可以获取保存 cookie 的正确实例

标签: c# asp.net-core


【解决方案1】:

一种可能性是将 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));

【讨论】:

  • 太棒了!在解决时像一个魅力一样工作:var container = HttpContext.RequestServices.GetService(typeof(CookieContainer)) as CookieContainer; container.Add(new Uri("https://localhost"), new Cookie("token", user.Token));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-16
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 1970-01-01
相关资源
最近更新 更多