Из замечательного курса Кевина в Pluralsight - Использование HttpClient для использования API в NET Core ....
У меня есть только сомнения по поводу того, как вызвать поток входа в Identity Server 4 при работе с недопустимым ответы внутри службы клиента http.
Просто упомяните, что, как предложил Кевин, мне удалось создать обработчик делегирования аутентификации, который установит правильный токен-носитель в запросе сообщения http-запроса.
Я хотел бы добавить новый делегирующий обработчик для запуска потока входа в систему Identity Server 4 в случае, если код статуса http не авторизован.
Кажется, что более кратким является добавление дополнительной ответственности к клиентской службе http.
Что делать ты думаешь? Это можно сделать?. Заранее спасибо.
(Ниже я публикую код клиентской службы http, а также обработчика делегирования аутентификации и соответствующей конфигурации запуска)
Краткий код запуска
services
.AddSingleton<IClientAuthenticationOptions>(new ClientAuthenticationOptions
{
Authority = "http.....",
ClientId = "Game",
ClientSecret = "secret"
});
services
.AddTransient<AuthenticationDelegatingHandler>();
services
.AddHttpClient()
.AddHttpClient<IBaseHttpClient, BaseHttpClient>(client =>
{
client.BaseAddress = new Uri("http...);
})
.AddHttpMessageHandler<AuthenticationDelegatingHandler>()
.ConfigurePrimaryHttpMessageHandler(handler => new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
});
Http-клиент службы
using Marvin.StreamExtensions;
using Shared.Asp.Interfaces;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace Shared.Asp.Helpers
{
public class BaseHttpClient : IBaseHttpClient
{
private readonly HttpClient _httpClient;
private readonly CancellationTokenSource _cancellationTokenSource;
public BaseHttpClient(HttpClient httpClient)
{
_httpClient = httpClient;
_cancellationTokenSource = new CancellationTokenSource();
_httpClient.DefaultRequestHeaders.Accept.Clear();
}
public async Task<T> GetAsync<T>(string requestUri)
{
using var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, _cancellationTokenSource.Token);
if (!response.IsSuccessStatusCode) // inspect the status code
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
DO SOMETHING HERE TO TRIGGER THE LOGIN FLOW OR USE OTHER DelegatingHandler FOR SO;
response.EnsureSuccessStatusCode();
}
var stream = await response.Content.ReadAsStreamAsync();
return await stream.ReadAndDeserializeFromJsonAsync<T>();
}
}
}
Обработчик делегирования аутентификации
using IdentityModel.Client;
using Microsoft.AspNetCore.Http;
using Shared.Abs.Interfaces;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using static Shared.Asp.Extensions.HttpClientExtensions;
namespace Shared.Asp.DelegatingHandlers
{
public class AuthenticationDelegatingHandler : DelegatingHandler
{
private readonly HttpClient _httpClient;
private readonly IHttpContextAccessor _contextAccessor;
private readonly IClientAuthenticationOptions _authenticationOptions;
public AuthenticationDelegatingHandler(IHttpClientFactory clientFactory, IHttpContextAccessor contextAccessor, IClientAuthenticationOptions authenticationOptions)
{
_contextAccessor = contextAccessor;
_authenticationOptions = authenticationOptions;
_httpClient = clientFactory.CreateClient();
}
public AuthenticationDelegatingHandler(HttpMessageHandler innerHandler, IHttpClientFactory clientFactory, IHttpContextAccessor contextAccessor, IClientAuthenticationOptions authenticationOptions)
: base(innerHandler)
{
_contextAccessor = contextAccessor;
_authenticationOptions = authenticationOptions;
_httpClient = clientFactory.CreateClient();
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var accessToken = await _httpClient.GetAccessTokenAsync(_contextAccessor.HttpContext, _authenticationOptions);
request.SetBearerToken(accessToken);
return await base.SendAsync(request, cancellationToken);
}
}
}
Метод таможенного расширения _httpClient .GetAccessTokenAsyn c (_ contextAccessor.HttpContext, _authenticationOptions) обрабатывает обновление токена ... (не включено для краткости)