即使没有 CA 匹配,也强制 ASP.NET WebAPI 客户端发送客户端证书
Posted
技术标签:
【中文标题】即使没有 CA 匹配,也强制 ASP.NET WebAPI 客户端发送客户端证书【英文标题】:Forcing ASP.NET WebAPI client to send a client certificate even when no CA match 【发布时间】:2013-10-08 04:27:57 【问题描述】:我有一个特定的应用程序,它需要使用客户端证书来相互验证 HTTPS 请求。服务器具有灵活的证书验证策略,允许它接受服务器证书存储中不存在的自签名客户端证书。众所周知,使用 curl 作为客户端可以正常工作。
我通过测试和数据包嗅探确定的是,Microsoft 的 ASP.NET HttpClient
在 SSL 握手期间试图过于智能。如果此特定客户端与服务器的受信任根之一具有信任链,则该特定客户端将仅使用客户端证书(来自WebRequestHandler.ClientCertificates
集合)。我观察到的是,如果没有具有信任链的证书,那么客户端在握手期间根本不会发送证书。
这是可以理解的默认行为,但过于严格,似乎无法将其关闭。我尝试了各种其他WebRequestHandler
属性,包括AuthenticationLevel
和ClientCertificateOptions
,但无济于事。
有没有办法强制HttpClient
在ClientCertificates
集合中可用时发送客户端证书,即使它似乎不会在服务器端验证?我对直接和肮脏(反射黑客)的解决方案持开放态度,因为我真的需要这个客户端来工作。
【问题讨论】:
你找到解决办法了吗? 对这个问题有什么想法吗? 2018 年仍然如此 :( 【参考方案1】:我认为您有多个证书或需要多个证书并需要附加它们。 您可以向 X509CertificateCollection 添加尽可能多的证书。 其中之一必须与 https 服务器证书匹配,否则您无法调用 Web 服务。
try
X509Certificate2 clientCert = GetClientCertificate("cert1");
X509Certificate2 clientCert = GetClientCertificate("cert2");
X509Certificate2 clientCert = GetClientCertificate("cert3");
WebRequestHandler requestHandler = new WebRequestHandler();
requestHandler.ClientCertificates.Add(clientCert1);
requestHandler.ClientCertificates.Add(clientCert2);
requestHandler.ClientCertificates.Add(clientCert3); HttpClient 客户端 = 新 HttpClient(requestHandler) BaseAddress = new Uri("http://localhost:3020/") ;
HttpResponseMessage response = client.GetAsync("customers").Result;
response.EnsureSuccessStatusCode();
string responseContent = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseContent);
catch (Exception ex)
Console.WriteLine("Exception while executing the test code: 0", ex.Message);
然后调用这个请求。
private static X509Certificate2 GetClientCertificate( string probablerightcert)
X509Store userCaStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
userCaStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificatesInStore = userCaStore.Certificates;
X509Certificate2Collection findResult = certificatesInStore.Find(X509FindType.FindBySubjectName, probablerightcert, true);
X509Certificate2 clientCertificate = null;
if (findResult.Count == 1)
clientCertificate = findResult[0];
else
throw new Exception("Unable to locate the correct client certificate.");
return clientCertificate;
catch
throw;
finally
userCaStore.Close();
【讨论】:
【参考方案2】:我有同样的问题,同样没有运气。还观察到一个奇怪的行为,当 WebRequesthandler 有时确实发送证书时,这取决于线程/AppPool 凭据。
我已经通过用 RestClient 替换 HttpClient 来解决这个问题。 RestClient 是开源的,可通过 nuget 获得。
RestSharp page
API 非常相似,无需担心证书即可完成所需的魔法:
var restClient = new RestClient($"serviceBaseUrlrequestUrl");
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;
【讨论】:
以上是关于即使没有 CA 匹配,也强制 ASP.NET WebAPI 客户端发送客户端证书的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Web API 与 ASP.NET Core 中的 URL 匹配差异
web api - asp.net 身份令牌即使对于后续请求也会过期