【问题标题】:How to attach a certificate to the InnerHandler of a DelegatingHandler如何将证书附加到 DelegatingHandler 的 InnerHandler
【发布时间】:2019-10-12 11:11:04
【问题描述】:

我必须在对外部来源的请求中使用证书。

委托处理程序封装了请求 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
        }
    }

    ///...

【问题讨论】:

    标签: asp.net-core asp.net-web-api oauth-2.0 asp.net-core-webapi


    【解决方案1】:

    我已经让它工作了,我在依赖注入中为处理程序配置了证书,所以我从处理程序类中提取了GetCertificate 方法。我已经修改了代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-12
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-09
      相关资源
      最近更新 更多