2009-05-21 33 views
9

Dường như tôi đã đặt câu hỏi sai trong bài viết trước đó của tôi. Tôi có một dịch vụ web được bảo mật bằng chứng chỉ X.509, hoạt động như một trang web bảo mật (https://...). Tôi muốn sử dụng chứng chỉ máy của máy khách (cũng X.509) do CA gốc của công ty phát hành để xác minh với máy chủ rằng máy khách được ủy quyền sử dụng dịch vụ. Để thực hiện điều này, tôi cần kiểm tra chứng chỉ và tìm một số tính năng nhận dạng và so khớp với một giá trị được lưu trữ trong cơ sở dữ liệu (có thể là Dấu vân tay?).Làm cách nào để nhận được chứng nhận X509Certificate từ máy khách trong dịch vụ web?

Đây là mã tôi sử dụng để có được giấy chứng nhận từ các cửa hàng giấy chứng nhận địa phương (cất thẳng từ http://msdn.microsoft.com/en-us/magazine/cc163454.aspx):

public static class SecurityCertificate 
{ 
    private static X509Certificate2 _certificate = null; 

    public static X509Certificate2 Certificate 
    { 
     get { return _certificate; } 
    } 

    public static bool LoadCertificate() 
    { 
     // get thumbprint from app.config 
     string thumbPrint = Properties.Settings.Default.Thumbprint; 
     if (string.IsNullOrEmpty(thumbPrint)) 
     { 
      // if no thumbprint on file, user must select certificate to use 
      _certificate = PickCertificate(StoreLocation.LocalMachine, StoreName.My); 
      if (null != _certificate) 
      { 
       // show certificate details dialog 
       X509Certificate2UI.DisplayCertificate(_certificate); 
       Properties.Settings.Default.Thumbprint = _certificate.Thumbprint; 
       Properties.Settings.Default.Save(); 
      } 
     } 
     else 
     { 
      _certificate = FindCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, thumbPrint); 
     } 

     if (null == _certificate) 
     { 
      MessageBox.Show("You must have a valid machine certificate to use STS."); 
      return false; 
     } 

     return true; 
    } 

    private static X509Certificate2 PickCertificate(StoreLocation location, StoreName name) 
    { 
     X509Store store = new X509Store(name, location); 
     try 
     { 
      // create and open store for read-only access 
      store.Open(OpenFlags.ReadOnly); 

      X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindByIssuerName, STSClientConstants.NBCCA, true); 
      if (0 == coll.Count) 
      { 
       MessageBox.Show("No valid machine certificate found - please contact tech support."); 
       return null; 
      } 

      // pick a certificate from the store 
      coll = null; 
      while (null == coll || 0 == coll.Count) 
      { 
       coll = X509Certificate2UI.SelectFromCollection(
         store.Certificates, "Local Machine Certificates", 
         "Select one", X509SelectionFlag.SingleSelection); 
      } 

      // return first certificate found 
      return coll[ 0 ]; 
     } 
     // always close the store 
     finally { store.Close(); } 
    } 

    private static X509Certificate2 FindCertificate(StoreLocation location, StoreName name, X509FindType findType, string findValue) 
    { 
     X509Store store = new X509Store(name, location); 
     try 
     { 
      // create and open store for read-only access 
      store.Open(OpenFlags.ReadOnly); 

      // search store 
      X509Certificate2Collection col = store.Certificates.Find(findType, findValue, true); 

      // return first certificate found 
      return col[ 0 ]; 
     } 
     // always close the store 
     finally { store.Close(); } 
    } 

Sau đó, tôi đính kèm giấy chứng nhận cho luồng dữ liệu ra bên ngoài thusly:

public static class ServiceDataAccess 
{  
    private static STSWebService _stsWebService = new STSWebService(); 

    public static DataSet GetData(Dictionary<string,string> DictParam, string action) 
    { 
     // add the machine certificate here, the first web service call made by the program (only called once) 
     _stsWebService.ClientCertificates.Add(SecurityCertificate.Certificate); 
     // rest of web service call here... 
    } 
} 

Câu hỏi của tôi là điều này - làm cách nào để "nhận" chứng chỉ trong mã dịch vụ web? Hầu hết các đoạn mã mẫu tôi đã đi qua bìa đó làm thế nào để làm xác nhận tùy chỉnh có một cuộc gọi GetCertificate() trong đó, dường như giả định rằng một phần là dễ dàng như vậy tất cả mọi người nên biết làm thế nào để làm điều đó?

Lớp chính của tôi kế thừa từ WebService, vì vậy tôi có thể sử dụng Context.Request.ClientCertificate để lấy chứng chỉ, nhưng đó là một HttpClientCertificate chứ không phải X509Certificate2. HttpContext cho tôi kết quả tương tự. Các cách tiếp cận khác đều sử dụng mã cấu hình web để gọi mã xác minh được xác định trước, không có đầu mối về cách gọi phương thức C# tùy chỉnh để thực hiện xác minh.

Tôi chắc chắn đây là một "câu hỏi ngu ngốc" khác mà ai đó sẽ quay lại và nói "hãy xem, chỉ cần làm điều này và nó hoạt động", nhưng điều đó là ổn. Tôi đã dành nhiều giờ cố gắng để có được điều này để làm việc, và niềm tự hào của tôi là gần như không tồn tại vào thời điểm này. Ai đó có thể cho tôi thấy lỗi của con đường của tôi không?

Cảm ơn, Dave

+0

Nếu bạn không có HttpContext, hãy xem câu trả lời cho http: // stackoverflow.com/questions/7528455/how-to-get-the-x509certificate-from-a-client-yêu cầu? lq = 1 –

Trả lời

12

Tôi nhớ lại làm một cái gì đó tương tự, được của nó một lúc nhưng, bạn đã thử điều này trong dịch vụ web của bạn:

X509Certificate2 cert = new X509Certificate2(Context.Request.ClientCertificate.Certificate); 
+0

Điều đó có hiệu quả! Bây giờ tôi cuối cùng có thể nhận được thịt của vấn đề của tôi - tìm ra những giá trị tôi có thể sử dụng để phù hợp với một giá trị được lưu trữ trong cơ sở dữ liệu ... Cảm ơn !! – DaveN59

+1

Dấu vân tay là tốt để sử dụng nếu bạn đang xử lý cơ sở dữ liệu của mình với tư cách là cơ quan đáng tin cậy, tôi đã làm việc trên các ứng dụng đã thực hiện phương pháp này. OTOH, nếu bạn cần một mô hình tin cậy phân tán (sử dụng CA), thì bạn cần thực hiện các kiểm tra bổ sung (ví dụ: xác minh chuỗi chứng chỉ). – DSO

+0

Tôi nghĩ rằng tôi có thể đã hành động quá sớm. Cố gắng truy cập Thumbprint ném ngoại lệ 'System.Security.Cryptography.CryptographicException' - vì vậy, mặc dù Chứng chỉ http bây giờ thuộc loại X509Certificate2, nó thực sự là cùng một chứng chỉ được gửi từ máy khách hay tôi vừa tạo một con thú mà trông giống như nó? – DaveN59

1

Về chủ đề làm thế nào để buộc chứng chỉ lại cho người dùng, vì vậy giả sử danh tính của người dùng được liên kết với khóa là tốt (vì chứng chỉ đã được xác minh trở lại một thư mục tin cậy và không b een bị thu hồi) thì bạn cần phải buộc danh tính được xác nhận bởi chứng chỉ cho người dùng. Bạn chỉ có thể sử dụng dạng chuỗi LDAP của chủ đề DN và tìm kiếm nó (cn = Tên người dùng, ou = Bộ phận ...) để xác định ID cục bộ. Đây là khả năng phục hồi trong trường hợp người dùng tái tạo khóa/chứng chỉ của họ nói vì mất thẻ hoặc hết hạn tự nhiên của chứng chỉ. Điều này dựa trên thực tế là hai CA sẽ không phát hành hai certs với cùng một tên chủ đề cho hai người khác nhau.

Nếu chứng chỉ được cấp bởi MS CA, nó có thể có UPN trong đó có hiệu quả là tên đăng nhập tên miền.

Hoặc nếu bạn muốn kết hợp danh tính của người dùng với chứng chỉ thực tế, phương pháp thông thường là lưu trữ tên tổ chức phát hành và số sê-ri chứng chỉ. CA phải phát hành số sêri duy nhất cho mỗi chứng chỉ. Lưu ý số sê-ri có thể lớn tùy thuộc vào CA. Tuy nhiên, không sử dụng phương pháp này thì có nghĩa là các chi tiết chứng chỉ trong cơ sở dữ liệu phải được cập nhật mỗi khi chứng chỉ người dùng được cấp lại.

+1

Thông tin tuyệt vời! Nếu tôi vẫn đang làm việc trong dự án, đây chính xác là loại thông tin tôi cần để khắc phục các vấn đề tôi đã tạo trong lần triển khai đầu tiên. Tuy nhiên, vì bây giờ tôi đã chuyển đến một công ty khác với các trách nhiệm khác nhau, tôi sẽ để đó là một bài tập cho người khác ... Cảm ơn phản hồi! – DaveN59

Các vấn đề liên quan