我有一个我无法解决的具体问题。让我详细解释一下。我是这项技术的新手,所以我可能会使用一些错误的术语。如果您不理解,请更正并解释或要求解释。 我正在创建一个托管在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示例相同。
任何人都可以告诉我这种方法出错了吗?
如果您需要更多信息,请询问。
谢谢
答案 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客户端,例如WebClient或HttpWebRequest或HttpClient V.prototype或HttpClient V.Next,请坚持使用webHttpBinding。
很抱歉没有解决您的直接问题,但您可能会遇到更多问题,因为您使用的绑定旨在使非WCF平台可以访问WCF服务,然后使用WCF尝试访问它。