c# - 绕过证书验证

标签 c# ssl

我无法绕过生产服务器中的证书验证,因为从未调用过 ServicePointManager.ServerCertificateValidationCallback:

ServicePointManager.ServerCertificateValidationCallback = ValidateRemoteCertificate;

...

private bool ValidateRemoteCertificate(
    object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
    LogActionToTable(EntrySeverity.Information, 
        $"ValidateRemoteCertificate() Certificate name: {cert.Subject}");
    return true;
}

从 Web 应用程序中的方法调用时,该行永远不会执行奇怪足够从单元测试 (NUnit) 正确调用它。 p>

我确实在对远程 API 的任何其他调用之前添加了此调用。

我做错了什么?

如果我只是这样做,它甚至都不起作用:

ServicePointManager
  .ServerCertificateValidationCallback += 
    (sender, cert, chain, sslPolicyErrors) => true;

这一定很简单,但我已经用了好几天了,我无法让它正常工作。


无论我是在手动构建 XML 的地方使用 RestSharp 调用,还是通过 wsdl.exe 工具生成的代理进行调用,我总是从调用中得到这个:

The request was aborted: Could not create SSL/TLS secure channel.

并在日志文件中启用 Trace,我得到:

System.Net 信息:0:[7912] SecureChannel#14469269 - 证书的类型为 X509Certificate2 并包含私钥。 System.Net 信息:0:[7912] AcquireCredentialsHandle(包 = Microsoft 统一安全协议(protocol)提供程序,意图 = 出站,scc = System.Net.SecureCredential) System.Net 信息:0:[7912] InitializeSecurityContext(凭证 = System.Net.SafeFreeCredential_SECURITY,上下文 =(空),targetName = onni.unicom.fi,inFlags = ReplayDetect,SequenceDetect, secret 性,AllocateMemory,InitManualCredValidation) System.Net 信息:0:[7912] InitializeSecurityContext(缓冲区内长度=0,缓冲区外长度=170,返回代码=ContinueNeeded)。 System.Net 信息:0:[7912] InitializeSecurityContext(凭证 = System.Net.SafeFreeCredential_SECURITY,上下文 = 14899210:2119fd0,targetName = onni.unicom.fi,inFlags = ReplayDetect,SequenceDetect, secret 性,AllocateMemory,InitManualCredValidation) System.Net 信息:0:[7912] InitializeSecurityContext(In-Buffers count=2,Out-Buffer length=0,返回代码=CredentialsNeeded)。 System.Net 信息:0:[7912] SecureChannel#14469269 - 我们有用户提供的证书。服务器已指定 1 个颁发者。寻找与任何颁发者相匹配的证书。 System.Net 信息:0:[7912] SecureChannel#14469269 - 剩下 0 个客户端证书可供选择。 System.Net 信息:0:[7912] 使用缓存的凭据句柄。 System.Net 信息:0:[7912] InitializeSecurityContext(凭证 = System.Net.SafeFreeCredential_SECURITY,上下文 = 14899210:2119fd0,targetName = onni.unicom.fi,inFlags = ReplayDetect,SequenceDetect, secret 性,AllocateMemory,InitManualCredValidation) System.Net 信息:0:[7912] InitializeSecurityContext(缓冲区内计数=2,缓冲区外长度=173,返回代码=ContinueNeeded)。 System.Net 信息:0:[7912] InitializeSecurityContext(凭证 = System.Net.SafeFreeCredential_SECURITY,上下文 = 14899210:2119fd0,targetName = onni.unicom.fi,inFlags = ReplayDetect,SequenceDetect, secret 性,AllocateMemory,InitManualCredValidation) System.Net 信息:0:[7912] InitializeSecurityContext(缓冲区内计数=2,缓冲区外长度=0,返回代码=CertUnknown)。 System.Net 错误:0:[7912] HttpWebRequest 中的异常#25731266::- 请求已中止:无法创建 SSL/TLS 安全通道。 System.Net 错误:0:[7912] HttpWebRequest 中的异常#25731266::EndGetRequestStream - 请求被中止:无法创建 SSL/TLS 安全通道。

最重要的:

System.Net Information: 0 : [7912] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CertUnknown).

为什么 ServicePointManager.ServerCertificateValidationCallback 调用没有绕过它?


没有代理的代码:

    private CardBalanceInfo ApiGetCardBalance(string cardNumber)
    {
        LogActionToTable(EntrySeverity.Information, $"ApiGetCardBalance('{cardNumber}')");

        var soapEnvelope =
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                "  <soap:Header/>" +
                "  <soap:Body>" +
                "    <csi:getBalance xmlns:csi=\"urn:si.tm.webservice.uniassociation.unicom.com\">" +
                "      <csi:balanceId>" +
               $"        <entityName>{cardNumber}</entityName>" +
                "      </csi:balanceId>" +
                "    </csi:getBalance>" +
                "  </soap:Body>" +
                "</soap:Envelope>";

        const string soapUrl = "treasurymanagement/si";
        const string soapAction = "http://www.unicom.fi/uAASTreasuryManagementSI/getBalance";
        var response = MakeApiCall(soapUrl, soapAction, soapEnvelope);

        return response.ToBalanceInfo();
    }

代理代码:

    private CardBalanceInfo ApiGetCardBalanceFromProxy(string cardNumber)
    {
        LogActionToTable(EntrySeverity.Information, $"ApiGetCardBalanceFromProxy('{cardNumber}')");

        using (var service = new uAASTreasuryManagementSIService())
        {
            service.Timeout = 10000; // 10 sec
            service.Url = _settings.BaseUrl.TrimEnd('/') + "/treasurymanagement/si";
            service.ClientCertificates.Add(_clientCertificate);

            var card = new getBalance()
            {
                balanceId = new EntityId
                {
                    entityName = cardNumber
                }
            };

            var balanceResponse = service.getBalance(card); // get API response

            LogActionToTable(EntrySeverity.Information, $"ApiGetCardBalanceFromProxy success.");

            return new CardBalanceInfo()
            {
                AvailableBalance = balanceResponse.balance.availableBalanceValue,
                Balance = balanceResponse.balance.balanceValue,
                BalanceId = balanceResponse.balance.balanceId.ToString()
            };
        }
    }

最佳答案

我不认为证书验证是您的问题。

ServerCertificateValidationCallback在对证书进行自定义验证时使用。这在证书的主机名与您调用的服务的 URL 不匹配的开发或质量检查环境中最常需要。

您会知道何时遇到此问题,因为您会收到包含以下错误详细信息的 SecurityNeogtiationException:

其他信息:无法与权限“{HOSTNAME}”建立 SSL/TLS 安全通道的信任关系

这是我在本地计算机上关闭 ServerCertificateValidationCallback 时的样子。

enter image description here

我建议您将注意力转移到

The request was aborted: Could not create SSL/TLS secure channel.

因为这似乎是完全不同的问题。幸运的是,我还没有遇到 :-) 这里的答案将是一个很好的起点:The request was aborted: Could not create SSL/TLS secure channel

HTH

关于c# - 绕过证书验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37032525/

相关文章:

c# - 一个字符的不同 ASCII 值

c# - 检索当前的 Outlook 约会

c# - 比较 2 字符串

security - SSLVPN 是否使您的 http 请求加密?

python - 在 python 2.7.9 中禁用默认证书验证

c# - 使用 JsonWriter 时,WriteStartConstructor 的用途是什么?

c# - 使用 System.IO.Packaging 创建大型 ZIP 文件时出现 OutOfMemoryException

php - 混合内容 : The page at 'url' was loaded over HTTPS, 但在 Opencart 中请求不安全的图像

java - 带有客户端证书的 https 请求在 android 中返回访问被拒绝,但在 post man 中效果很好,retrofit 和 okhttp3 返回相同的错误

ios - 带有客户端证书的 SecTrustSetAnchorCertificates