Я использую IHttpClientFactory для отправки запросов и получения HTTP-ответов от внешних API-интерфейсов с использованием Net Core 2.2.
Я реализовал DelegatingHandler для «перехвата» моего http-запроса и добавления заголовка авторизации (Token).если токен недействителен, он получает новый токен и повторяет попытку еще раз.
Аналогично, когда я впервые получаю новый токен, я кеширую токен в памяти для дальнейших ссылок.Для кеширования токена я создал словарь, который требует accountID и токен.
Проблема, с которой я столкнулся, состоит в том, что DelegatingHandler зарегистрирован в классе Startup.cs, но в тот момент у меня нет accountID, я получаю accountID в качестве параметра в ActionMethod Контроллера.Этот метод действия вызывает метод SendAsync и получает токен от DelegatingHandler и т. Д.
Я не знаю, как я могу внедрить этот accountID в DelegatingHandler после получения запроса в контроллере.
Я пытался создать интерфейс IClientCredentials и реализовать этот интерфейс, который может быть создан в контроллере и внедрен в DelegatingHandler.
Мой код выглядит следующим образом:
DelegatingHandler:
public class AuthenticationDelegatingHandler : DelegatingHandler
{
private readonly AccessTokenManager _accessTokenManager;
private readonly IClientCredentials _clientCredentials;
public AuthenticationDelegatingHandler(IHttpClientFactory httpClientFactory,
IOptions<AppSettings> appSettings, IClientCredentials clientCredentials)
{
_accessTokenManager = new AccessTokenManager(httpClientFactory, appSettings);
_clientCredentials = clientCredentials;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var clientCredentials = _clientCredentials.GetClientCredentials();
var accessToken = _accessTokenManager.GetToken(clientCredentials._accountID);
if (accessToken == null) {
accessToken = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
_accessTokenManager.AddOrUpdateToken(clientCredentials._accountID, accessToken);
}
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.access_token);
var response = await base.SendAsync(request, cancellationToken);
if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
{
var token = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
response = await base.SendAsync(request, cancellationToken);
}
return response;
}
}
Startup.cs так:
services.AddScoped<IClientCredentials>(_ => new
ClientCredentials("au","123"));
services.AddHttpClient("myClient")
.AddHttpMessageHandler<AuthenticationDelegatingHandler>();
И контроллер:
[HttpPost("{siteName}/{accountID}")]
public async Task<ActionResult<AirRequest>> Post(AirModel model, string
siteName, string accountID)
{
....
SetClientCredentials(siteName, accountID);
var clientJAAPI =
_httpClientFactory.CreateClient("myClient");
var responseclientJAAPI = await
clientJAAPI.SendAsync(request);
.....
}
private ClientCredentials SetClientCredentials(string siteName, string
accountID) =>
new ClientCredentials(siteName, accountID);