简体   繁体   English

如何将证书附加到 DelegatingHandler 的 InnerHandler

[英]How to attach a certificate to the InnerHandler of a DelegatingHandler

I have to use a certificate in an request to an external source.我必须在对外部来源的请求中使用证书。

The delegating handler wraps the job of requesting an API key and then making the request with the API key.委托处理程序包装请求 API 密钥的作业,然后使用 API 密钥发出请求。 I am able to attach the certificate to the request for the API key and obtain the API key but I am also supposed to attach the certificate to the actual request but not sure how to attach it to the InnerHandler我可以将证书附加到 API 密钥的请求中并获取 API 密钥,但我也应该将证书附加到实际请求中,但不确定如何将其附加到InnerHandler

Can anyone please show me how to do this?谁能告诉我如何做到这一点?

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
        }
    }

    ///...

I have got it working, I configure the certificate for the handler in dependency injection so I pulled out the GetCertificate method from the handler class.我已经让它工作了,我在依赖注入中为处理程序配置了证书,所以我从处理程序 class 中提取了GetCertificate方法。 I have amended the code.我已经修改了代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM