2015-03-17 5 views
1

Я пытаюсь загрузить файл на FTP-сервер, и мне нужно использовать сертификат клиента для аутентификации, а не имя пользователя и пароль.Есть ли способ использовать FtpWebRequest для аутентификации на FTP с использованием клиентских сертификатов на C#?

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

Выше мой текущий код, но я не уверен, как осуществить проверку подлинности сертификата или, если это вообще возможно, чтобы сделать это. Мне нужно создать сертификат? Или сервер предоставит мне сертификат, и я просто установлю его в моем запросе?

ответ

0
  • Используйте FtpWebRequest.ClientCertificates property указать сертификат, используемый для аутентификации
  • Сертификат о type X509Certificate
  • Вы либо построить сертификат самостоятельно (из массива или импорта байт из файла), или посмотреть его в магазин сертификата (X509Store)
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); 
+0

Развейте вопрос, строка индивидуального кода, я должен создать его? Сертификат, который я ищу в магазине, выдается сервером, к которому я пытаюсь подключиться? и нужно ли мне имя пользователя, даже если я использую аутентификацию сертификата? – FurqanRauf

+0

Как правило, вы создаете сертификат и предоставляете администратору сервера свой открытый ключ, или если это сертификат, подписанный CA, вам может и не понадобиться его предоставлять. Или вы отправляете запрос на подпись сертификата администратору сервера. Есть много вариантов. Это немного выходит за рамки вашего вопроса. Вам лучше спросить новый. Или сделать некоторые исследования. Что касается имени пользователя: я считаю, что обычно вам нужно использовать имя пользователя. Я могу представить, что имя пользователя может не понадобиться, но я еще не видел такой настройки. –

0

Вы можете использовать ComponentPro для этого. This 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(); 

 Смежные вопросы

  • Нет связанных вопросов^_^