【问题标题】:Certificate validation/installation for FTPS (SSL)?FTPS (SSL) 的证书验证/安装?
【发布时间】:2013-10-20 02:33:12
【问题描述】:

我使用 FileZilla 作为服务器和 DNS 服务,这样我就不必使用我的本地计算机 IP(但我在这两种方法上都尝试了以下方法)。

在尝试 System.Net.FtpWebRequest 工作后,我已经阅读(包括一些关于 SO 的帖子)并发现 SSL 支持对于该库来说不是很充分。它使用常规 FTP,但是当我尝试强制使用 SSL 时,我收到证书验证错误:The remote certificate is invalid according to the validation procedure.

所以,我进行了一些搜索并找到了 Alex FTPS 客户端 库。这是我写的代码:

class FTPSWorker
    {
        public static void UploadFile(string sourceFile, string targetFile, string ftpIP, string ftpUser, string ftpPass)
        {
            try
            {
                using (FTPSClient client = new FTPSClient())
                {
                    client.Connect(ftpIP, new NetworkCredential(ftpUser, ftpPass),
                                   ESSLSupportMode.CredentialsRequired | ESSLSupportMode.DataChannelRequested);
                    client.SetTransferMode(ETransferMode.Binary);
                    client.PutFile(sourceFile, targetFile);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

不幸的是,我遇到了完全相同的证书错误。但是,我可以使用 FileZilla 客户端完美地访问 FTP 服务器。所以,我认为肯定有证书问题。

我应该注意到我的服务器显示了以下日志条目:

Welcome Message
AUTH TLS
234 Using authentication type TLS
SSL connection established
disconnected

当客户端(C# WPF 应用程序)收到此错误时:

The remote certificate is invalid according to the validation procedure.

如果我使用 .NET 库和 MSDN 代码,这绝对是完全相同的错误。

我进行了更多研究并找到了类似以下的解决方案:

The remote certificate is invalid according to the validation procedure

"The remote certificate is invalid according to the validation procedure." using Gmail SMTP server

但它们看起来像是有风险的黑客......虽然它们确实有效,但除了当前使用的基本是/否之外,是否有办法显示认证信息并可能让用户验证/安装它?

我现在的代码(我放弃了 Alex 的库并回到默认的 .NET):

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(FTPWorker.ValidateServerCertificate);

public class FTPWorker
{
    public static void UploadFile(string sourceFile, string targetFile, string ftpIP, string ftpUser, string ftpPass)
    {
        try
        {
            string filename = "ftp://" + ftpIP + "/test/" + targetFile;
            FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
            ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
            ftpReq.Credentials = new NetworkCredential(ftpUser, ftpPass);
            ftpReq.UsePassive = true;
            ftpReq.EnableSsl = true;
            ftpReq.UseBinary = true;
            ftpReq.KeepAlive = false;

            byte[] b = File.ReadAllBytes(sourceFile);

            ftpReq.ContentLength = b.Length;

            using (Stream s = ftpReq.GetRequestStream())
            {
                s.Write(b, 0, b.Length);
            }

            FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();

            if (ftpResp != null)
            {
                MessageBox.Show(ftpResp.StatusDescription);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
        }
    }

    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;
        else
        {
            if (System.Windows.Forms.MessageBox.Show("The server certificate is not valid.\nAccept?", 
                   "Certificate Validation", System.Windows.Forms.MessageBoxButtons.YesNo,
                   System.Windows.Forms.MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                return true;
            else
                return false;
        }
    }
}

【问题讨论】:

  • 您的代码绝对可以将证书呈现给用户进行检查,并且可能应该显示证书验证的具体问题,因为在验证回调中返回给您的代码。

标签: c# ssl ftp filezilla ftps


【解决方案1】:

如果您指定,Alex ftps 将执行相同的证书验证。 在您的 client.connect 中添加 remotecertificatevalidationcallback 以接受证书

client.Connect(ftpIP, new NetworkCredential(ftpUser, ftpPass),
                               ESSLSupportMode.CredentialsRequired | ESSLSupportMode.DataChannelRequested, 
                           new RemoteCertificateValidationCallback(ValidateTestServerCertificate));

然后在下面。

private static bool ValidateTestServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        // Accept any certificate
        return true;
    }

我想使用默认的 .net。但我坚持连接到使用隐式的服务器。 :(

【讨论】:

  • 是的,我没有说他的库不会这样做,只是我不需要它,因为.NET提供的库以相同的方式工作,在那个特定情况。我在原始帖子中提供的链接与您提供的解决方案相同。我只是不喜欢他们,因为他们默默地接受了证书。显然,您仍然可以通知用户,但是开始回调只是额外的工作。无论哪种方式,您都接受在本地创建的证书,而不是实际签名的证书。不过,使用他的图书馆是一种更快捷的方式。
【解决方案2】:

因此,对于遇到相同问题的任何人,我最终只是根据我在原始帖子中提供的链接向用户发出有关证书的警告以及接受或拒绝的选项。为了验证证书,它必须是真实的,而不是本地创建的。所以,这是目前唯一的解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-05
    • 2016-08-30
    • 2015-08-20
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    相关资源
    最近更新 更多