Я использую IHttpClientFactory для отправки запросов и получения HTTP-ответов от двух внешних API-интерфейсов с использованием Net Core 2.2.
Я ищу хорошую стратегию для получения нового токена доступа с использованием сохраненного токена обновленияв appsettings.json.Новый токен доступа необходимо запрашивать, когда текущий запрос возвращает ошибки 403 или 401. Когда новый токен доступа и обновления получены, файл appsettings.json необходимо обновить новыми значениями, чтобы использовать в последующих запросах.
Я использую два клиента для отправки запросов двум разным API, но только один из них использует механизм аутентификации токена.
Я реализовал нечто простое, которое работает, но я ищу более элегантное решениекоторый может динамически обновлять заголовок после истечения срока действия текущего токена:
Я зарегистрировал IHttpClientFactory в методе Startup.ConfigureServices следующим образом:
services.AddHttpClient();
После регистрации я использую его в двухразные методы для вызова двух разных API, первый метод:
public async Task<AirCallRequest> GetInformationAsync(AirCallModel model)
{
try
{
CandidateResults modelCandidateResult = null;
var request = new HttpRequestMessage(HttpMethod.Get,
"https://*******/v2/*****");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _appSettings.Value.Token);
var clientJAAPI = _httpClientFactory.CreateClient();
var responseclientJAAPI = await clientJAAPI.SendAsync(request);
if (responseclientJAAPI.IsSuccessStatusCode)
{
modelCandidateResult = await responseclientJAAPI.Content
.ReadAsAsync<CandidateResults>();
....
}
if ((responseclientJAAPI .StatusCode.ToString() == "Unauthorized")
{
await RefreshAccessToken();
//Calls recursively this method again
return await GetInformationAsync(model);
}
return null;
}
catch (Exception e)
{
return null;
}
}
Метод Token обновления выглядит так:
private async Task RefreshAccessToken()
{
var valuesRequest = new List<KeyValuePair<string, string>>();
valuesRequest.Add(new KeyValuePair<string, string>("client_id", "*****"));
valuesRequest.Add(new KeyValuePair<string, string>("client_secret","****"));
valuesRequest.Add(new KeyValuePair<string, string>("grant_type", "refresh_token"));
valuesRequest.Add(new KeyValuePair<string, string>("refresh_token", "*****"));
RefreshTokenResponse refreshTokenResponse = null;
var request = new HttpRequestMessage(HttpMethod.Post,
"https://*****/connect/token");
request.Content = new FormUrlEncodedContent(valuesRequest);
var clientJAAPI = _httpClientFactory.CreateClient();
var responseclientJAAPI = await clientJAAPI.SendAsync(request);
if (responseclientJAAPI.IsSuccessStatusCode)
{
refreshTokenResponse = await responseclientJAAPI.Content.ReadAsAsync<RefreshTokenResponse>();
//this updates the POCO object representing the configuration but not the appsettings.json :
_appSettings.Value.Token = refreshTokenResponse.access_token;
}
}
Обратите внимание, что я обновляю объект POCO, представляющий конфигурациюно не appsettings.json, поэтому новые значенияхранится в памяти.Я хочу обновить appsettings.json для последующих запросов.
Если предлагаемое решение требует определения основных параметров для Httpclient в Startup.ConfigureService, ему необходимо разрешить создание разных экземпляров HttpClien, поскольку один из экземпляров HttpClient (используйте в другом методе для вызовавторой API) не требует токен для отправки запросов.