WCF,REST,SSL,客户端,自定义证书验证
我有一个我无法解决的特定问题。让我详细解释一下。我对这项技术很陌生,所以我可能会使用一些错误的术语。如果您不明白,请纠正并解释或要求解释。 我正在创建一个自我托管的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示例中的相同。
任何人都可以请告诉我在哪里我会错用这种方法?
如果您需要更多信息,请询问。
谢谢
如果你想使用WCF客户端,那么就不要使用的WebHttpBinding,坚持使用SOAP东西,它会运行得更好。
但是,如果您要使用标准HTTP客户端,如WebClient或HttpWebRequest或3210或HttpClient V.Next,请使用webHttpBinding。
对不起,没有解决您的直接问题,但您可能会遇到更多问题,因为您使用的绑定旨在让WCF服务可供非WCF平台访问,但之后使用WCF尝试访问它。
看起来像是问题发生,因为证书是针对其他主机名发布的。您可以通过提供自定义的ServicePointManager.ServerCertificateValidationCallback来检查它(并在必要时自定义)。
//不使用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;
}
嗨达雷尔,感谢您的回答。我正在使用WebHttpBinding,因此我可以在移动平台上支持多种类型的客户端(即Win7,Android,iPhone)。我想先创建WinForms客户端,以了解我需要做什么。 – elector 2011-01-21 14:17:58
@elector很酷。只要确保你使用标准的HTTP客户端而不是WCF频道。这样,不同平台上的客户将会更加一致地工作。 – 2011-01-21 14:28:08
感谢Darrel,听起来很酷,但恐怕我不知道标准http客户端是什么意思? :)你知道c#中的例子很快吗?或者,我应该谷歌什么?正如我所说,我是新手,所以每一点信息都有很大的帮助。 – elector 2011-01-21 14:32:42