【问题标题】:Is there a way to use FtpWebRequest to authenticate to FTP using client certificates in C#?有没有办法使用 FtpWebRequest 在 C# 中使用客户端证书对 FTP 进行身份验证?
【发布时间】:2015-03-17 20:43:17
【问题描述】:

我正在尝试将文件上传到 FTP 服务器,我需要使用客户端证书而不是用户名和密码进行身份验证。

var fullFtpPath = String.Concat(ftpItem.FtpAddress, "/", record, ".txt");

FtpWebRequest request = (FtpWebRequest) WebRequest.Create(fullFtpPath);
request.Credentials = new NetworkCredential(ftpItem.Username, ftpItem.Password);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UseBinary = true;
request.UsePassive = ftpItem.UsePassive;
request.EnableSsl = ftpItem.UseSSL;

request.ContentLength = bytes.Length;
using(Stream s = request.GetRequestStream()) {
    s.Write(bytes, 0, bytes.Length);
}

FtpWebResponse response = (FtpWebResponse) request.GetResponse();
Debug.WriteLine("Upload File Complete, status {0}", response.StatusDescription);

db.LogExport(siteId, fullFtpPath, record, true, response.StatusDescription);
response.Close();

以上是我当前的代码,但我不确定如何实现证书身份验证,或者是否可以这样做。我必须创建证书吗?或者服务器会给我一个证书,我就在我的请求中设置它?

【问题讨论】:

    标签: c# ssl ftp client-certificates ftps


    【解决方案1】:
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com");
    
    request.Credentials = new NetworkCredential("username", "");
    
    // Query certificate from store
    X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly);
    const string tp = "2b6f8ac51a85cbaf429474a55304313968667611";
    X509Certificate2 cert2 =
        store.Certificates.Find(X509FindType.FindByThumbprint, tp, true)[0];
    store.Close();
    
    // Add certificate into request
    request.ClientCertificates.Add(cert2);
    

    【讨论】:

    • 跟进问题,指纹字符串,我必须生成它吗?我在商店中寻找的证书是由我要连接的服务器颁发的吗?即使我使用证书身份验证也需要用户名吗?
    • 通常你生成一个证书并向服务器管理员提供它的公钥,或者如果它是一个由 CA 签名的证书,你可能根本不需要提供它。或者您向服务器管理员发送证书签名请求。有很多选择。这有点超出您的问题范围。你最好问一个新的。或者做一些研究。关于用户名:我相信通常你需要使用用户名。我可以想象可能不需要用户名,但我还没有看到这样的设置。
    【解决方案2】:

    您可以为此使用ComponentProThis code example 解释了如何使用证书对客户端进行身份验证:

    using System;
    using System.Security.Cryptography.X509Certificates;
    using ComponentPro.Net;
    
    ...
    
    public void HandleCertificateRequiredEvent()
    {
        // Create a new instance.
        Ftp client = new Ftp();
    
        client.CertificateRequired += client_CertificateRequired;
    
        // Connect to the FTP server.
        client.Connect("myserver", 21, FtpSecurityMode.Explicit);
    
        // Authenticate.
        client.Authenticate("userName", "password");
    
        // Do something here...
        client.DownloadFile("/my remote file.dat", "my local file");
    
        // Disconnect.
        client.Disconnect();
    }
    
    void client_CertificateRequired(object sender, ComponentPro.Security.CertificateRequiredEventArgs e)
    {
        // Load certificates from the local machine.
        X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        my.Open(OpenFlags.ReadOnly);
    
        // Retrieve a list of available certificates.
        X509Certificate2Collection certs = my.Certificates;
    
        // If no certificate found, return.
        if (certs.Count == 0)
        {
            e.Certificates = null;
            return;
        }
    
        // Show all certificates.
        Console.WriteLine("Select certificate:");
        for (int i = 0; i <= certs.Count; i++)
        {
            if (i == 0)
            {
                Console.WriteLine(string.Format("{0}. [Nothing, skip this step]", i));
                continue;
            }
    
            Console.WriteLine(string.Format("{0}. {1}", i, certs[i - 1].SubjectName.Name));
        }
    
        // And ask user to choose an appropriate certificate.
        while (true)
        {
            Console.Write(string.Format("Select certificate [0 - {0}]: ", certs.Count));
    
            int certIndex;
    
            try
            {
                certIndex = int.Parse(Console.ReadLine());
            }
            catch
            {
                Console.WriteLine("ERROR: Wrong certificate index input!");
                continue;
            }
    
            if (certIndex > 0 && certIndex <= certs.Count)
            {
                e.Certificates = new X509Certificate2Collection(certs[certIndex]);
                return;
            }
    
            if (certIndex == 0)
                break;
    
            Console.WriteLine(string.Format("ERROR: You must enter number between 0 and {0}.", certs.Count));
        }
    }
    

    ComponentPro 也很好用 with FtpWebRequest

    using System;
    using System.IO;
    using System.Net;
    
    ...
    
    // Register FtpWebRequest for the specified schema.
    WebRequest.RegisterPrefix("ftp://", ComponentPro.Net.FtpWebRequest.Creator);
    
    Console.WriteLine("Sending request...");
    
    // Create a WebRequest for the specified URL.
    WebRequest request = WebRequest.Create("ftp://ftp.example.net/pub/myfile.zip");
    
    // Send the WebRequest and waits for a response.
    WebResponse response = request.GetResponse();
    
    // Get remote file stream for downloading.
    Stream remoteFileStream = response.GetResponseStream();
    
    Stream localFileStream = File.Create("myfile.zip");
    
    // Create a new buffer to download.
    byte[] buffer = new byte[1024];
    int n;
    do
    {
        // Read data from the remote file stream.
        n = remoteFileStream.Read(buffer, 0, buffer.Length);
        // Write to the local file stream.
        localFileStream.Write(buffer, 0, n);
    } while (n > 0);
    
    Console.WriteLine("Response Received.");
    
    localFileStream.Close();
    
    // Release the resources of the response.
    remoteFileStream.Close();
    

    【讨论】:

    • FWIW,请参阅 cheated.by.safabyte.net,它显示 Component Pro 可能代表被盗软件的最新版本。 TY
    猜你喜欢
    • 2012-01-10
    • 2021-02-11
    • 2015-10-29
    • 2018-07-05
    • 2019-01-14
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多