Попробуйте использовать HttpClientFactory
, который был добавлен Asp.Net Core 2.1, вместе с HttpMessageHandler
для достижения того, что вы пытаетесь сделать.
Вы можете зарегистрировать HttpClient в методе ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<BaseClient>(client =>
{
client.BaseAddress = new Uri("yrl");
client.DefaultRequestHeaders.Add("Accept", "application/json");
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});
}
При наличии вышеуказанного кода ваш BaseClient
получит экземпляр HttpClient через DI.
Для проверки / проверки AuthHeader
вы можете настроить HttpMessageHandler
для зарегистрированных HttpClient
.Код для обработчика сообщений прост, как показано ниже:
public class AuthHeaderHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (!request.Headers.Contains("Authorization"))
{
return new HttpResponseMessage(HttpStatusCode.Forbidden)
{
Content = new StringContent("No Authorization header is present")
};
}
return await base.SendAsync(request, cancellationToken);
}
}
Чтобы зарегистрировать вышеуказанный обработчик, ваш код будет выглядеть следующим образом:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<AuthHeaderHandler>();
services.AddHttpClient<BaseClient>(client =>
{
//code omitted for brevity
...
})
.AddHttpMessageHandler<AuthHeaderHandler>();
}
Вы можете ввести все, что вам нужновнутри обработчика сообщений, если это необходимо.Однако нет необходимости внедрять IHttpContextAccessor в BaseClient
.Чтобы узнать больше о HttpClientFactory и HttpMessageHandlers, перейдите по ссылкам и по .Я надеюсь, что это поможет.
ОБНОВЛЕННЫЙ ОТВЕТ
Пожалуйста, взгляните на более конкретный пример HttpMessageHandler, который использует IHttpContextAccessor и изменяет HttpRequestMessage, т.е. добавляет заголовок авторизации перед тем, какзвонок сделан.Вы можете изменить логику в соответствии со своими потребностями.
public class AuthHeaderHandler : DelegatingHandler
{
private readonly HttpContext _httpContext;
public AuthHeaderHandler(IHttpContextAccessor contextAccessor)
{
_httpContext = contextAccessor.HttpContext;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (_httpContext != null)
{
var accessToken = await _httpContext.GetTokenAsync(TokenKeys.Access);
if (!string.IsNullOrEmpty(accessToken))
{
// modify the request header with the new Authorization token
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
}
return await base.SendAsync(request, cancellationToken);
}
}
ОБНОВЛЕННЫЙ ОТВЕТ 2
Пожалуйста, взгляните на простое решение , которое язагрузили на GitHub.Решение даже проще, чем я изначально предлагал.Поскольку вы не интегрируете аутентификацию / авторизацию на основе идентификации, вы можете просто использовать CustomActionFilter, я назвал его ValidateAuthHeader
, чтобы проверить, присутствует ли AuthHeader или нет, и вернуть обычные 403, если таковые отсутствуют.
В ValidateAuthHeader
я использовал код промежуточного программного обеспечения, который вы разместили ранее.Затем вы можете просто добавить этот атрибут в ActionMethods или Controllers, которые требуют этой проверки.
Пожалуйста, посмотрите на DataController
и ValuesController
.DataController
получит напечатанный HttpClient
, который будет использоваться для вызова конечной точки values
.ValidateAuthHeader
присутствует на GetValues
и проверит наличие AuthHeader.Если он отсутствует, он выдаст ошибку.
[Route("api/[controller]")]
[ApiController]
public class DataController : ControllerBase
{
private readonly MyHttpClient _client;
public DataController(MyHttpClient client)
{
_client = client;
}
[ValidateAuthHeader]
public async Task<IActionResult> GetValues()
{
var response = await _client.GetAsync("api/values");
var contents = await response.Content.ReadAsStringAsync();
return new ContentResult
{
Content = contents,
ContentType = "application/json",
StatusCode = 200
};
}
}
Остальная часть потока такая же, как я изначально предлагал.Вызов будет проходить через AuthHeaderHandler
, который является HttpMessageHandler
для зарегистрированного MyHttpClient
.Пожалуйста, посмотрите на Startup.cs
.
. Обработчик извлечет HttpContext
через HttpContextAccessor
и проверит наличие AuthHeader
.Если он присутствует, он добавит его в параметр RequestMessage.
Надеюсь, это поможет.Не стесняйтесь задавать любые вопросы, которые могут у вас возникнуть.
Настройка заголовка аутентификации без использования HttpMessageHandler
Измените MyHttpClient и добавьте открытый метод с именем SetAuthHeader
public class MyHttpClient
{
private readonly HttpClient _httpClient;
public MyHttpClient(HttpClient client)
{
_httpClient = client;
}
public void SetAuthHeader(string value)
{
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", value);
}
}
Затем вызовите этот метод в своем методе действия, так как в этот момент у вас будет AuthHeader в HttpContext.Request
[ValidateAuthHeader]
public async Task<IActionResult> GetValues()
{
var authHeader = Request.Headers["Authorization"];
_client.SetAuthHeader(authHeader.First());
var response = await _client.GetAsync("api/values");
var contents = await response.Content.ReadAsStringAsync();
return new ContentResult
{
Content = contents,
ContentType = "application/json",
StatusCode = 200
};
}
Удалите регистрацию AuthHeaderHandler и удалите AuthHeaderHandler.