我无法绕过生产服务器中的证书验证,因为永远不会调用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)中正确调用。
我确实在对远程API的任何其他调用之前添加了此调用。
我做错了什么?
如果我这样做,它甚至都不起作用:ServicePointManager
.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
这一定非常简单,但是我已经好几天了,而且我无法正常使用它。
无论我使用的是RestSharp调用,我手动构建XML,还是通过wsdl.exe
工具生成的代理调用,我总是从调用中得到这个:
请求已中止:无法创建SSL / TLS安全通道。
并将Trace启用到日志文件中,我得到:
System.Net Information: 0 : [7912] SecureChannel#14469269 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [7912] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent = Outbound, scc = System.Net.SecureCredential)
System.Net Information: 0 : [7912] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = (null), targetName = onni.unicom.fi, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7912] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=170, returned code=ContinueNeeded).
System.Net Information: 0 : [7912] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 14899210:2119fd0, targetName = onni.unicom.fi, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7912] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CredentialsNeeded).
System.Net Information: 0 : [7912] SecureChannel#14469269 - We have user-provided certificates. The server has specified 1 issuer(s). Looking for certificates that match any of the issuers.
System.Net Information: 0 : [7912] SecureChannel#14469269 - Left with 0 client certificates to choose from.
System.Net Information: 0 : [7912] Using the cached credential handle.
System.Net Information: 0 : [7912] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 14899210:2119fd0, targetName = onni.unicom.fi, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7912] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=173, returned code=ContinueNeeded).
System.Net Information: 0 : [7912] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 14899210:2119fd0, targetName = onni.unicom.fi, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [7912] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CertUnknown).
System.Net Error: 0 : [7912] Exception in HttpWebRequest#25731266:: - The request was aborted: Could not create SSL/TLS secure channel..
System.Net Error: 0 : [7912] Exception in HttpWebRequest#25731266::EndGetRequestStream - The request was aborted: Could not create SSL/TLS secure channel..
最重要的是:
System.Net信息:0:[7912] InitializeSecurityContext(In-Buffers count = 2,Out-Buffer length = 0,返回代码= 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()
};
}
}
答案 0 :(得分:0)
我认为证书验证不是您的问题。
在进行证书的自定义验证时使用ServerCertificateValidationCallback。这在dev或qa环境中最常需要,其中证书的主机名与您正在呼叫的服务的URL不匹配。
您知道何时遇到此问题,因为您将收到带有以下错误详细信息的SecurityNeogtiationException:
其他信息:无法与具有权限的SSL / TLS安全通道建立信任关系&#39; {HOSTNAME}&#39;
以下是我在本地计算机上关闭ServerCertificateValidationCallback时的情况。
我建议您将注意力转移到
因为这似乎是完全不同的问题。幸运的是,我还没遇到过:-)这里的答案将是一个很好的起点:The request was aborted: Could not create SSL/TLS secure channel请求已中止:无法创建SSL / TLS安全通道。
HTH