Forcing ASP.NET WebAPI client to send a client certificate even when no CA match

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-09 05:43:41

问题


I have a specific application that requires the use of client certificates for mutual authentication of HTTPS requests. The server has a flexible certificate validation policy that allows it to accept self-signed client certificates that are not present in the server's certificate store. This is known to work just fine using curl as a client.

What I've determined via testing and packet sniffing is that Microsoft's ASP.NET HttpClient tries to be overly smart during the SSL handshake. This particular client will only use a client certificate (from the WebRequestHandler.ClientCertificates collection) if it has chain of trust to one of the server's trusted roots. What I've observed is that if there are no certificates with chain of trust then the client simply won't send a certificate at all during the handshake.

This is understandable default behavior but is overly restrictive and there appears to be no way to turn it off. I have experimented with various other WebRequestHandler properties, including AuthenticationLevel and ClientCertificateOptions but to no avail.

Is there a way to force HttpClient to send a client certificate when it is available in the ClientCertificates collection, even though it appears that it will not validate on the server side? I'm open to both straightforward and dirty (reflection hacks) solutions as I really need this client to work.


回答1:


I had the same issue and same no luck. Also observed a strange behaviour, when WebRequesthandler sometimes did send the certificate, depending on the thread / AppPool credentials.

I have managed to sort this out by replacing HttpClient with RestClient. RestClient is OpenSource and available via nuget.

RestSharp page

The API is very similar and does the required magic without moaning about the certificate:

        var restClient = new RestClient($"{serviceBaseUrl}{requestUrl}");
        X509Certificate certificate = GetCertificateFromSomewhere();
        restClient.ClientCertificates = new X509CertificateCollection { certificate };
        var request = new RestRequest(Method.POST);
        request.RequestFormat = DataFormat.Json;
        request.AddParameter(new Parameter()
        {
            Type = ParameterType.RequestBody,
            Name = "Body",
            ContentType = "application/json",
            Value = "{your_json_body}"
        });

        IRestResponse<T> response = client.Execute<T>(request);
        if (response.ErrorException != null)
        {
            throw new Exception(response.Content, response.ErrorException);
        }
        return response.Data;


来源:https://stackoverflow.com/questions/19125896/forcing-asp-net-webapi-client-to-send-a-client-certificate-even-when-no-ca-match

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!