.NET 6 HttpClient调用IIS部署的带默认SSL证书Web API问题及解决
.NET 6客户端调用本地IIS Web API的证书问题解决
场景说明
我用.NET 6构建了Web API及对应客户端应用,Web API部署在本地网络的IIS中,使用IIS默认生成的SSL证书。从Google Chrome下载该证书后,编写了如下客户端调用代码:
internal static async Task<(bool, string, GeneralAnswer<UserAccess>)> UserAccessPost(string alias, string password, WebServiceParams _params) { try { string json = JsonSerializer.Serialize(new { usr_alias = alias, usr_password = password }); var data = new StringContent(json, Encoding.UTF8, "application/json"); X509Certificate2 Cert = new X509Certificate2(@"C:\Users\egomez\source\repos\Trazo_Registro_Tienda_Administracion _nuevo_webservice\ClassLibraryWebServiceConnect\Operations\Certificates\WMSvc-SHA2-GTLTATSW01W16.crt"); HttpClientHandler handler = new HttpClientHandler(); handler.ClientCertificates.Add(Cert); handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2; var client = new HttpClient(handler); client.Timeout = TimeSpan.FromSeconds(_params._TIMEOUT_WEB_SERVICE); var response = await client.PostAsync(_params._IP_WEB_SERVICE + "api/Access/", data); if (response.StatusCode == System.Net.HttpStatusCode.OK) { var result = await response.Content.ReadAsStringAsync(); return ( true, "Respuesta del servidor obtenida con exito.", JsonSerializer.Deserialize<GeneralAnswer<UserAccess>>(result)); } else { return ( false, "Error al obtener credenciales. Estatus: " + response.StatusCode, null); } } catch (Exception ex) { return ( false, "Error, Excepcion: " + ex.Message.ToLower(), new GeneralAnswer<UserAccess>()); } }
异常原因
调用时出现异常,排查后确认是**该IIS默认证书不被信任,且缺少SAN(主题备用名称)**导致SSL验证失败。
解决方案
1. 编写自定义证书验证方法
通过校验证书哈希值,手动信任目标证书:
internal static bool ValidateServerCertificate(HttpRequestMessage message, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors policy) { return certificate.GetCertHashString() == "88D664F25FEE8A99CDA8B1041B708AE6808B061D"; }
2. 修改客户端调用逻辑
移除原有的客户端证书添加代码,将ServerCertificateCustomValidationCallback指向自定义验证方法:
internal static async Task<(bool, string, GeneralAnswer<UserAccess>)> UserAccessPost(string alias, string password, WebServiceParams _params) { try { string json = JsonSerializer.Serialize(new { usr_alias = alias, usr_password = password }); var data = new StringContent(json, Encoding.UTF8, "application/json"); HttpClientHandler handler = new HttpClientHandler(); handler.ServerCertificateCustomValidationCallback = Certificate.ValidateServerCertificate; var client = new HttpClient(handler); client.Timeout = TimeSpan.FromSeconds(_params._TIMEOUT_WEB_SERVICE); var response = await client.PostAsync(_params._IP_WEB_SERVICE + "api/Access/", data); if (response.StatusCode == System.Net.HttpStatusCode.OK) { var result = await response.Content.ReadAsStringAsync(); return ( true, "Respuesta del servidor obtenida con exito.", JsonSerializer.Deserialize<GeneralAnswer<UserAccess>>(result)); } else { return ( false, "Error al obtener credenciales. Estatus: " + response.StatusCode, null); } } catch (Exception ex) { return ( false, "Error, Excepcion: " + ex.Message.ToLower(), new GeneralAnswer<UserAccess>()); } }
修改完成后,客户端即可正常调用Web API。
内容的提问来源于stack exchange,提问作者Edgar Gomez
相关产品推荐
相关产品推荐

