FTP下载文件生成错误:呼叫SSPI失败

发布于 2025-02-12 01:59:30 字数 1229 浏览 3 评论 0 原文

我正在尝试从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);

I am trying to download a file from my FTP Server but from my production server (from my laptop I am able to download the file) I get the error "A call to SSPI failed" and the inner exception "The message received was unexpected or badly formatted". This my code:

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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

放飞的风筝 2025-02-19 01:59:30

sspi 是Windows组件。
如果您在Windows 2008上,则意味着它很旧。

错误“收到的消息是出乎意料或格式不佳”似乎表明服务器证书
使用不支持的格式(例如,使用未知密码),因此无法通过SSPI层处理。

您有几个解决方案:

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

SSPI is a Windows component.
If you are on Windows 2008, it means it's very old.

The error "The message received was unexpected or badly formatted" seems to indicate that the server certificate
uses an unsupported format (for instance, uses an unknown cipher), and thus can't be processed by the SSPI layer.

You have several solutions:

  • Upgrade Windows
  • Downgrade the server certificate
  • Don't use SSL
  • Use an alternative FTP library that does not rely on SSPI
若无相欠,怎会相见 2025-02-19 01:59:30

要在.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)文件。然后将它们像下面一样使用到您的代码中。

有关更多信息,请参见下面的lonk

参考

也许此链接也为您提供帮助。

祝你好运

To use SSL certificate inside .Net framework we need to provide both certificate and its corresponding private key together. To achieve this we need to use p12(.pfx) file which combined this two. In my project, I have used self-signed certificate using OpenSSL so I used below command to combine certificate and private key

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

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

which will create p12(.pfx) file for each certificate. Then used them into your code like below .

see below lonk for more information

Reference

maybe this link also help you .

Good luck

ぇ气 2025-02-19 01:59:30

根据先前的建议,您的代码应该看起来像这样:

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);

注意:我没有测试解决方案,因为我没有环境对其进行测试

Based on the previous suggestions your code should look like this:

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);

Note: I have not tested the solution because I don't have an environment to test it on

笑着哭最痛 2025-02-19 01:59:30

TLS握手失败了,因为两个服务器无法就通用密码套件达成共识。

iis crypto 以启用Web App Server上的其他密码套件。下载并运行了IIS加密,在重新启动机器之后,在其密码套件选项卡上在其Cipher Suites选项卡上进行了检查。

如果诊断失败,我建议您安装 wireshark> wireshark 带有.NET核心应用程序的机器上。
如果再次进行TLS握手故障,则一条邮件类似:ALERT(级别:致命,描述:握手失败
某些密码套件比其他套件更安全,因此Check Ref Link可能有助于解决您的问题。

临时解决方案:
使用Windows注册表设置Schannel的最小密钥长度:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ClientMinKeyBitLength"=dword:00000200

ref: link2 link3 link4

The TLS handshake was failing because two servers were unable to agree on a common cipher suite.

IIS Crypto to enable additional cipher suites on web app's server. downloaded and ran IIS Crypto, checkmarked additional cipher suites on its Cipher Suites tab after then restarted the machine.

If diagnose failure, I'd recommend installing Wireshark on the machine with your .NET Core app.
If TLS Handshake Failure again,a message like: Alert (Level: Fatal, Description: Handshake Failure)
Some cipher suites are more secure than others, so check ref link may help to solve your problem.

temporary solution:
set the minimum key length for schannel using windows registry:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ClientMinKeyBitLength"=dword:00000200

Ref: Link1, link2, link3 ,Link4

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文