FTP Download File generate the error: A call to SSPI failed



我正试图从我的FTP服务器下载文件,但从我的生产服务器(从我的笔记本电脑,我能够下载该文件)我得到错误"对SSPI的调用失败了";以及内部异常"收到的消息出乎意料或格式错误"。这是我的代码:

var ftpServer = "ftp://xxx.yyy.zz/";
var ftpUsername = "aaaaa";
var ftpPassword = "bbbbb";
var downloadedFilePath = "c:\temp\";
var downloadedFileName = "file.xls";                      
FtpWebRequest request = null;
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
return true;
};
// Get the object used to communicate with the server.
request = (FtpWebRequest)WebRequest.Create(ftpServer + "file_on_ftp_server.xls");
// download the file
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
request.EnableSsl = true;
request.KeepAlive = false;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();    // <--- ERROR
Stream responseStream = response.GetResponseStream();
FileStream writer = new FileStream(downloadedFilePath + downloadedFileName, FileMode.Create);

SSPI是Windows组件。如果你用的是Windows 2008,那就意味着它很老了。

错误"收到的消息出乎意料或格式错误"。似乎表明服务器证书使用不支持的格式(例如,使用未知的密码),因此不能被SSPI层处理。

你有几个解决方案:

  • 升级Windows
  • 降级服务器证书
  • 不要使用SSL
  • 使用不依赖于SSPI的替代FTP库

要在。net框架内使用SSL证书,我们需要同时提供证书和相应的私钥。要实现这一点,我们需要使用p12(.pfx)文件,它结合了这两个。在我的项目中,我使用OpenSSL使用自签名证书,所以我使用下面的命令将证书和私钥组合在一起

pkcs12 -export -out ca.pfx -inkey ca.key -in ca.crt
pkcs12 -export -out client.pfx -inkey client.key -in client.crt

将为每个证书创建p12(.pfx)文件。然后在代码中使用它们,如下所示:

见下文,查找更多信息

参考

也许这个链接对你也有帮助。

好运

根据前面的建议,您的代码应该是这样的:

var ftpServer = "ftp://xxx.yyy.zz/";
var ftpUsername = "aaaaa";
var ftpPassword = "bbbbb";
var downloadedFilePath = "c:\temp\";
var downloadedFileName = "file.xls";                      
var certName = "MyCertName"   //Use yours
var password = "MyCertPassword";   //Use yours
FtpWebRequest request = null;
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
return true;
};
//Load certificates (one or more)
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
// Get the object used to communicate with the server.
request = (FtpWebRequest)WebRequest.Create(ftpServer + "file_on_ftp_server.xls");
// download the file
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
request.ClientCertificates = certificates;   //Use certificates
request.EnableSsl = true;
request.KeepAlive = false;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();    // <--- ERROR
Stream responseStream = response.GetResponseStream();
FileStream writer = new FileStream(downloadedFilePath + downloadedFileName, FileMode.Create);

注意:我没有测试解决方案,因为我没有一个环境来测试它

TLS握手失败,因为两个服务器无法就公共密码套件达成一致。

IIS Crypto在web应用的服务器上启用额外的密码套件。下载并运行IIS Crypto,在其"密码套件"选项卡上勾选"其他密码套件",然后重新启动计算机。

如果诊断失败,我建议在机器上安装Wireshark和你的。net Core应用。如果再次发生TLS握手失败,则发送如下消息:Alert (Level: Fatal, Description: Handshake Failure)有些密码套件比其他密码套件更安全,所以检查ref link可能有助于解决您的问题。

临时解决方案:
使用Windows注册表设置通道的最小键长度:

[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSecurityProvidersSCHANNELKeyExchangeAlgorithmsDiffie-Hellman]
"ClientMinKeyBitLength"=dword:00000200

Ref: Link1, link2, link3,Link4

相关内容

  • 没有找到相关文章

最新更新