使用 C#.Net 通过 FTPS (SSL/TLS) 传输文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1534908/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:30:49  来源:igfitidea点击:

Transfer files over FTPS (SSL/TLS) using C#.Net

c#sslftpwebrequestftps

提问by Eric Anastas

I'm writing an application that syncs files over an FTP site. Right now it's working by connecting through regular FTP, but now our IT guys want to set this up over a secure FTPS connection.

我正在编写一个通过 FTP 站点同步文件的应用程序。现在它通过常规 FTP 连接工作,但现在我们的 IT 人员希望通过安全的 FTPS 连接进行设置。

They provided me with a *.cr_ certificate file. If I open the file in notepad I see something like this (but with real keys not foobar obviously).

他们为我提供了 *.cr_ 证书文件。如果我在记事本中打开文件,我会看到类似的内容(但真正的键显然不是 foobar)。

-----BEGIN RSA PRIVATE   
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
FOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBARFOOBAR    
-----END CERTIFICATE-----

How can I use this certificate file to connect to the FTPS server to upload and download files? Forgive me but I'm very new to anything involving transferring files over a network, secure connections, certificates, public keys, private keys, etc...etc...

如何使用此证书文件连接FTPS服务器上传和下载文件?原谅我,但我对涉及通过网络传输文件、安全连接、证书、公钥、私钥等的任何事情都很陌生......

I think I'd want to use an FtpWebRequest object and set the EnableSsl property to true. But I'm not not sure where this certificate file comes into play.

我想我想使用 FtpWebRequest 对象并将 EnableSsl 属性设置为 true。但我不确定这个证书文件在哪里起作用。

回答by Eric J.

This articleexplains how to do it, with source code.

这篇文章用源代码解释了如何做到这一点。

The purpose of this article is to create a C # FTP client in Secure mode, so if you don't have much knowledge of FTPS, I advise you to take a look at this: FTPS.

In the .NET Framework, to upload a file in FTPS mode, we generally use the FtpWebRequest class, but you can not send commands with quote arguments, and even if you search on the web, you will not find a concrete example of a secured C# FTP client.

It's for those reasons I decided to create this article.

这篇文章的目的是在Secure模式下创建一个C#FTP客户端,所以如果你对FTPS不是很了解,我建议你看看这个:FTPS。

在.NET Framework中,以FTPS方式上传文件,我们一般使用FtpWebRequest类,但是不能发送带引号的命令,即使在网上搜索,也找不到具体的安全实例C# FTP 客户端。

正是出于这些原因,我决定创建这篇文章。

回答by JamieSee

If you're using the FtpWebRequest Class, you just need to add some things to the setup of the request to utilize a client certificate file. Be sure to include the using System.Security.Cryptography.X509Certificates;statement.

如果您使用的是FtpWebRequest Class,您只需要在请求的设置中添加一些内容即可使用客户端证书文件。请务必包含该using System.Security.Cryptography.X509Certificates;声明。

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
    request.Credentials = new NetworkCredential(userName, password);

    request.EnableSsl = true;
    //ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback;

    X509Certificate cert = X509Certificate.CreateFromCertFile(@"C:\MyCertDir\MyCertFile.cer");
    X509CertificateCollection certCollection = new X509CertificateCollection();
    certCollection.Add(cert);

    request.ClientCertificates = certCollection;

Also, if you have problems with the server certificate generating exceptions in the client you may need to implement your own certificate validation callback method for use with the ServicePointManager.ServerCertificateValidationCallback Property. This can be as simple as always returning true or be more sophisticated like the one I use for debugging:

此外,如果您在客户端中生成异常的服务器证书有问题,您可能需要实现自己的证书验证回调方法以与ServicePointManager.ServerCertificateValidationCallback 属性一起使用。这可以像总是返回 true 一样简单,也可以像我用于调试的那样更复杂:

    public static bool ServicePointManager_ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        bool allowCertificate = true;

        if (sslPolicyErrors != SslPolicyErrors.None)
        {
            Console.WriteLine("Accepting the certificate with errors:");
            if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch)
            {
                Console.WriteLine("\tThe certificate subject {0} does not match.", certificate.Subject);
            }

            if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                Console.WriteLine("\tThe certificate chain has the following errors:");
                foreach (X509ChainStatus chainStatus in chain.ChainStatus)
                {
                    Console.WriteLine("\t\t{0}", chainStatus.StatusInformation);

                    if (chainStatus.Status == X509ChainStatusFlags.Revoked)
                    {
                        allowCertificate = false;
                    }
                }
            }

            if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable)
            {
                Console.WriteLine("No certificate available.");
                allowCertificate = false;
            }

            Console.WriteLine();
        }

        return allowCertificate;
    }