2011-01-21 185 views
2

我有一個我無法解決的特定問題。讓我詳細解釋一下。我對這項技術很陌生,所以我可能會使用一些錯誤的術語。如果您不明白,請糾正並解釋或要求解釋。 我正在創建一個自我託管的WCF REST服務器,託管在WPF應用程序中。它使用https,SLL和WebHttpSecurityMode.Transport。我正在使用我自己生成的證書。 我想創建一個使用此服務的WinForms客戶端。來自服務器的響應格式是JSON。 我想通過從X509CertificateValidator繼承的自定義驗證器驗證客戶端上的證書。WCF,REST,SSL,客戶端,自定義證書驗證

這是我的服務器端代碼。我使用的是自定義用戶名驗證器,可以正常工作。我在我的機器上的IIS管理器中爲默認網站>綁定配置了證書,在那裏我生成了證書(Windows 7)。

WebServiceHost sh = new WebServiceHost(typeof(ReachService)); 
string uri = "https://localhost:9000/Service"; 
WebHttpBinding wb = new WebHttpBinding(); 
wb.Security.Mode = WebHttpSecurityMode.Transport; 
wb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 
sh.AddServiceEndpoint(typeof(IReachService), wb, uri); 
sh.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator(); 
sh.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom; 

sh.Open(); 

,這是關於調用service.GetCustomers()讓我的客戶端代碼

Uri uri = new Uri("https://localhost:9000/Service"); 
WebChannelFactory<ReachService> cf = new WebChannelFactory<IReachService>(uri); 
WebHttpBinding wb = cf.Endpoint.Binding as WebHttpBinding; 
wb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 
wb.Security.Mode = WebHttpSecurityMode.Transport; 
cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom; 
cf.Credentials.ServiceCertificate.Authentication.CustomCertificateValidator = new CustomCertificateValidator("PL2"); // this is the name that issued the certificate 
cf.Credentials.UserName.UserName = "user1"; 
cf.Credentials.UserName.Password = "user1"; 
IReachService service = cf.CreateChannel(); 
try 
{ 
    CustomersList auth = service.GetCustomers(); 
} 
catch (Exception ex) 
{ 
    throw new Exception(ex.Message); 
} 

: 無法與權威 爲SSL信任關係/ TLS安全通道的「localhost:9000 」。 InnerException消息: 底層連接已關閉:無法爲SSL/TLS安全通道建立信任關係。 InnerException消息: 根據驗證過程,遠程證書無效。

當我在瀏覽器中測試時服務器工作正常。 但客戶端代碼是錯誤的,因爲它沒有去定製的證書驗證器類。這個類與在http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.x509certificatevalidator.aspx上的MSDN示例中的相同。

任何人都可以請告訴我在哪裏我會錯用這種方法?

如果您需要更多信息,請詢問。

謝謝

回答

0

如果你想使用WCF客戶端,那麼就不要使用的WebHttpBinding,堅持使用SOAP東西,它會運行得更好。
但是,如果您要使用標準HTTP客戶端,如WebClientHttpWebRequest或​​3210或HttpClient V.Next,請使用webHttpBinding。

對不起,沒有解決您的直接問題,但您可能會遇到更多問題,因爲您使用的綁定旨在​​讓WCF服務可供非WCF平臺訪問,但之後使用WCF嘗試訪問它。

+0

嗨達雷爾,感謝您的回答。我正在使用WebHttpBinding,因此我可以在移動平臺上支持多種類型的客戶端(即Win7,Android,iPhone)。我想先創建WinForms客戶端,以瞭解我需要做什麼。 – elector 2011-01-21 14:17:58

+0

@elector很酷。只要確保你使用標準的HTTP客戶端而不是WCF頻道。這樣,不同平臺上的客戶將會更加一致地工作。 – 2011-01-21 14:28:08

+0

感謝Darrel,聽起來很酷,但恐怕我不知道標準http客戶端是什麼意思? :)你知道c#中的例子很快嗎?或者,我應該谷歌什麼?正如我所說,我是新手,所以每一點信息都有很大的幫助。 – elector 2011-01-21 14:32:42

1

看起來像是問題發生,因爲證書是針對其他主機名發佈的。您可以通過提供自定義的ServicePointManager.ServerCertificateValidationCallback來檢查它(並在必要時自定義)。

1

//不使用HttpWebRequest - 你失去了所有強類型的方法和數據契約!

//代碼來創建通道並調用一個方法:

SetCertPolicy(); 
var cf1 = new WebChannelFactory<TService>(new Uri(remoteServiceAddressSecure)); 
var service = cf1.CreateChannel(); 
sevice.DoMethod(); 

protected static void SetCertPolicy() 
     { 
      ServicePointManager.ServerCertificateValidationCallback += RemoteCertValidate; 
     } 

private static bool RemoteCertValidate(object sender, X509Certificate cert, X509Chain chain, 
       SslPolicyErrors error) 
     { 
      // trust any cert!!! 
      return true; 
     }