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

WCF、REST、SSL、客户端、自定义证书验证,wcf,rest,ssl,client,Wcf,Rest,Ssl,Client,我有一个我无法解决的具体问题。让我详细解释一下。我是这项技术的新手,所以我可能使用了一些错误的术语。如果你不明白,请改正并解释,或者要求解释。 我正在创建一个自托管的WCF REST服务器,托管在WPF应用程序中。它使用https、SLL和WebHttpSecurityMode.Transport。我正在使用自己生成的证书。 我想创建一个使用此服务的WinForms客户端。服务器响应表单的格式是JSON。 我想使用从X509CertificateValidator继承的自定义验证器在客户端验证证

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

这是我的服务器端代码。我使用的是一个自定义用户名验证程序,工作正常。我已在计算机上的IIS管理器中为默认网站>绑定配置了证书,并在其中生成了证书(Windows 7)

这是我的客户代码

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);
}
Uri=新的Uri(“https://localhost:9000/Service");
WebChannelFactory cf=新的WebChannelFactory(uri);
WebHttpBinding wb=cf.Endpoint.Binding作为WebHttpBinding;
wb.Security.Transport.ClientCredentialType=HttpClientCredentialType.Basic;
wb.Security.Mode=WebHttpSecurityMode.Transport;
cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode=X509CertificateValidationMode.Custom;
cf.Credentials.ServiceCertificate.Authentication.CustomCertificateValidator=新的CustomCertificateValidator(“PL2”);//这是颁发证书的名称
cf.Credentials.UserName.UserName=“user1”;
cf.Credentials.UserName.Password=“user1”;
IReachService=cf.CreateChannel();
尝试
{
CustomerList auth=service.GetCustomers();
}
捕获(例外情况除外)
{
抛出新异常(例如消息);
}
调用service.GetCustomers()时,我得到: 无法为具有权限的SSL/TLS安全通道建立信任关系 “localhost:9000”。 InnerException消息: 基础连接已关闭:无法为SSL/TLS安全通道建立信任关系。 InnerException消息: 根据验证过程,远程证书无效

在浏览器中测试时,服务器工作正常。 但是客户端代码是错误的,因为它没有进入自定义证书验证器类。这个类与上的MSDN示例相同

谁能告诉我这种方法哪里出了问题

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


谢谢你

如果你想在客户端上使用WCF,那么不要使用WebHttpBinding,坚持使用SOAP的东西,它会工作得更好。
然而,如果您想使用标准的HTTP客户机,比如webHttpBinding,那么请坚持使用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;
        }
SetCertPolicy();
var cf1=新的WebChannelFactory(新Uri(remoteServiceAddressSecure));
var service=cf1.CreateChannel();
服务。多门方法();
受保护的静态void SetCertPolicy()
{
ServicePointManager.ServerCertificateValidationCallback+=RemoteCertValidate;
}
私有静态bool RemoteCertValidate(对象发送方、X509证书证书证书、X509链、,
SslPolicyErrors(错误)
{
//相信任何证书!!!
返回true;
}

你好,达雷尔,谢谢你的回答。我正在使用WebHttpBinding,因此我可以在未来使用此服务器支持移动平台(即Win7、Android、iPhone)上的多种类型的客户端。我想先创建WinForms客户端,以了解我需要做什么。@elector太酷了。只需确保使用标准HTTP客户端而不是WCF通道。这样,您跨不同平台的客户端将更加一致地工作。谢谢Darrel,这听起来很酷,但我不知道您所说的标准http客户端是什么意思?:)你知道c#quick的一个例子吗?或者我应该用谷歌搜索什么?正如我所说,我是新手,所以每一点信息都很有用。我想他指的是HttpWebRequest,但用它代替WCF通常没有多大意义。嗨,康斯坦丁,谢谢你的回答。我在谷歌上搜索了一下,还找到了HttpWebRequest。我想这就是达雷尔的意思。也许使用它是有意义的,这样将代码移植到其他语言就更容易了。我将研究一下这个Konstantin,因为我不知道你指的是什么。感谢您的回答。只需在MSDN或Google中查找ServicePointManager类。它允许您自定义证书验证,通过提供自定义回调,您可以在那里放置断点,并查看默认验证中发现的错误。我相信Konstantin指的是证书中的服务器名称,它应该与您连接到的主机名相匹配(在本例中,可能是“localhost”)。服务器名称作为使用者名称的CN部分出现在证书中。或者,如果不匹配(即,它不是“localhost”),它可以显示为X509 V3证书扩展“Subject Alternative Name”作为“DNS”名称,例如,如果您使用openssl创建自己的证书,您可以将该名称放在自己的证书中。谢谢!我知道这是一种黑客行为,在生产中很危险,但你刚刚救了我一命!请注意,
ServicePointManager.ServerCertificateValidationCallback
是一个简单的委托属性,而不是事件。连接代理时,只有retur
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;
        }