У меня есть приложение веб-API NET Core 2. Во время процесса мне нужно вызвать API клиента A, чтобы получить некоторые данные. Поэтому я использую HttpClient для его вызова. Клиент A также требует, чтобы я передавал идентификатор пользователя и пароль в заголовке.
Поэтому вместо прямого введения HttpClient
у меня есть оболочка вокруг HttpClient
, как показано ниже
public class ClientA : IClientA
{
private readonly HttpClient _httpClient;
public ClientA(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<string> GetData()
{
return await _httpClient.HttpGetAsync("someurl");
}
}
Затем используйте ClientA в службе
public class MyService :IMyService
{
private readonly IClientA _clientA
public MyService(IClientA clientA)
{
_clientA= clientA
}
public void DoSomethig()
{
_clientA.GetData();
}
}
Потом все регистрирую в Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IMyService, MyService>();
services.AddScoped(factory =>
{
Func<Task<IClientA>> provider = async () =>
{
using (var dbContext = factory.GetService<MyDBContext>())
{
// get userid and password from database here
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("UserId",userid);
httpClient.DefaultRequestHeaders.Add("Password",password);
return new ClientA(httpClient);
}
};
return provider;
});
}
Однако я получаю сообщение об ошибке
System.InvalidOperationException: не удалось разрешить службу для типа «System.Net.Http.HttpClient» при попытке активировать «XXXXXXXXX.ClientA». в Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites (тип serviceType, тип implementationType, ISet
1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet
1 callSiteChain)
оставшееся исключение удалено для краткости
Обратите внимание, что во время регистрации я создаю новый экземпляр HttpClient
и передаю его классу ClientA, потому что мне нужно установить идентификатор пользователя и пароль.
Чтобы избавиться от указанной выше ошибки, я могу зарегистрировать HttpClient с идентификатором пользователя и паролем с помощью платформы DI, и я думаю, что это сработает.
Однако в этом случае, если есть другой клиент, ClientB, который принимает HttpClient, тогда инфраструктура DI внедрит тот же httpclient, у которого есть идентификатор пользователя и пароль. и это создаст проблему безопасности, потому что ClientB увидит учетные данные ClientA в заголовках запросов.
public class ClientB(HttpClient client)
{
private readonly _httpClient;
public class ClientB(HttpClient client)
{
_httpClient = client;
}
public string CallClientB(string url)
{
// here ClientB will receive ClientA's credentials
return await _httpClient.HttpGetAsync(url);
}
}
IOptions<MyHttpClientOptions>
. - person Brad   schedule 06.03.2018