代码之家  ›  专栏  ›  技术社区  ›  Anand

如何将证书附加到DelegatingHandler的InnerHandler

  •  0
  • Anand  · 技术社区  · 5 年前

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

    委托处理程序包装请求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
            }
        }
    
        ///...
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   Anand    5 年前

    我已经让它工作了,我在依赖注入中为处理程序配置了证书,所以我拉出了 GetCertificate 方法从处理程序类中删除。我已修订守则。