Как прикрепить сертификат к InnerHandler из DelegatingHandler - PullRequest
0 голосов
/ 11 октября 2019

Я должен использовать сертификат в запросе к внешнему источнику.

Обработчик делегирования оборачивает задачу запроса ключа API, а затем делает запрос с помощью ключа API. Я могу прикрепить сертификат к запросу на ключ API и получить ключ API, но я также должен прикрепить сертификат к фактическому запросу, но не уверен, как прикрепить его к InnerHandler

Может кто-нибудь, пожалуйста, покажите мне, как это сделать?

var thumbPrint = "xxxx"; // from settings
var builder = services
            .AddHttpClient("somename", c => c.BaseAddress = new Uri("someuri"))
            .AddHttpMessageHandler<GatewayOAuthHandler>()
            .ConfigurePrimaryMessageHandler(() => CreateHandler(GetCertificate(thumbPrint));


private X509Certificate2 GetClientCertificate(string thumbPrint)
{
    var userCaStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
    try
    {
        userCaStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
        var certificatesInStore = userCaStore.Certificates;
        X509Certificate2 clientCertificate = null;
        foreach (var certificate in certificatesInStore)
        {
            if (certificate.Thumbprint == thumbPrint)
            {
                clientCertificate = certificate;
                break;
            }
        }
        if (clientCertificate == null) throw new Exception();
        return clientCertificate;
    }
    catch
    {
        throw new Exception("Certificate not found.");
    }
    finally
    {
        userCaStore.Close();
    }
}

public class GatewayOAuthHandler : DelegatingHandler
{
    ///...

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var baseAddress = request.RequestUri.GetLeftPart(UriPartial.Authority);
        var scope = request.Headers.First(kvp => kvp.Key == "scope").Value.FirstOrDefault();
        string token = null;
        if (request.Headers.Authorization == null)
        {
            token = await GetTokenResponseAsync(baseAddress, scope, cancellationToken);
            if (token != null) request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        }

        var response = await base.SendAsync(request, cancellationToken);

        if (response.StatusCode != HttpStatusCode.OK)
        {
            var responseStr = response.Content.ReadAsStringAsync().Result;
            Logger.Log(LogLevel.Error, responseStr);
        }

        if (response.StatusCode != HttpStatusCode.Unauthorized) return response;

        token = await RefreshTokenResponse(baseAddress, scope, cancellationToken);
        if (token != null)
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
            response = await base.SendAsync(request, cancellationToken);
        }

        return response;
    }

    private async Task<string> GetTokenResponseAsync(string baseAddress, string scope, CancellationToken cancellationToken)
    {
        try
        {
            _semaphore.Wait(cancellationToken);
            if (cancellationToken.IsCancellationRequested) return null;
            if (!string.IsNullOrWhiteSpace(_accessToken)) return _accessToken;
            _accessToken = await SendTokenRequestAsync(baseAddress, scope);
            return _accessToken;
        }
        finally
        {
            _semaphore.Release();
        }
    }

    ///...

    private async Task<string> SendTokenRequestAsync(string baseAddress, string scope)
    {
        var consumerKey = await GetSecretAsync(_settings.ConsumerKeySecretId).ConfigureAwait(false);
        var consumerSecret = await GetSecretAsync(_settings.ConsumerSecretSecretId).ConfigureAwait(false);
        using (var request = new HttpRequestMessage(HttpMethod.Post, TokenUri))
        {
            request.Content = new StringContent($"grant_type=client_credentials&scope={scope}", Encoding.UTF8, "application/x-www-form-urlencoded"); ;
            request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{consumerKey}:{consumerSecret}")));
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
            var handler = new HttpClientHandler();
            var result = await new HttpClient(handler) { BaseAddress = new Uri(baseAddress) }.SendAsync(request);
            var tokenStr = await result.Content.ReadAsStringAsync();
            var token = JsonConvert.DeserializeObject<JObject>(tokenStr);
            return token["access_token"].ToString(); // API key
        }
    }

    ///...

1 Ответ

0 голосов
/ 12 октября 2019

У меня все работает, я настраиваю сертификат для обработчика при внедрении зависимости, поэтому я извлек метод GetCertificate из класса обработчика. Я изменил код.

...