WCF,REST,SSL,客户端,自定义证书验证

时间:2011-01-21 13:20:25

标签: wcf rest ssl client

我有一个我无法解决的具体问题。让我详细解释一下。我是这项技术的新手,所以我可能会使用一些错误的术语。如果您不理解,请更正并解释或要求解释。 我正在创建一个托管在WPF应用程序中的自托管WCF REST服务器。它使用https,SLL和WebHttpSecurityMode.Transport。我正在使用自己生成的证书。 我想创建一个使用此服务的WinForms客户端。服务器响应的格式是JSON。 我想使用从X509CertificateValidator继承的自定义验证器验证客户端上的证书。

这是我的服务器端代码。我正在使用自定义用户名验证器,工作正常。我已在我的计算机上的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();

这是我的客户代码

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

关于调用service.GetCustomers()我得到: 无法为具有权限的SSL / TLS安全通道建立信任关系 的 'localhost:9000'。 InnerException消息: 底层连接已关闭:无法为SSL / TLS安全通道建立信任关系。 InnerException消息: 根据验证程序,远程证书无效。

我在浏览器中测试时服务器工作正常。 但是客户端代码是错误的,因为它没有进入自定义证书验证器类。此类与http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.x509certificatevalidator.aspx上的MSDN示例相同。

任何人都可以告诉我这种方法出错了吗?

如果您需要更多信息,请询问。

谢谢

3 个答案:

答案 0 :(得分:1)

看起来问题出现是因为为其他主机名颁发了证书。您可以通过提供自定义ServicePointManager.ServerCertificateValidationCallback来检查(并在必要时进行自定义)。

答案 1 :(得分: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;
        }

答案 2 :(得分:0)

如果你想在客户端上使用WCF,那么不要使用WebHttpBinding,坚持使用SOAP,它会更好地工作。
但是,如果您要使用标准HTTP客户端,例如WebClientHttpWebRequestHttpClient V.prototypeHttpClient V.Next,请坚持使用webHttpBinding。

很抱歉没有解决您的直接问题,但您可能会遇到更多问题,因为您使用的绑定旨在​​使非WCF平台可以访问WCF服务,然后使用WCF尝试访问它。