[英]WCF, HTTPS vs HTTP
有兩個樣本
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
string addressHttps = String.Format("http://{0}:51222", Dns.GetHostEntry("").HostName);
var wsHttpBinding = new BasicHttpBinding();
var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));
Type endpoint = typeof (IHelloWorldService);
serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");
Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");
var smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.HttpGetUrl = uri;
serviceHost.Description.Behaviors.Add(smb);
Console.Out.WriteLine("Mex address " + smb.HttpGetUrl);
try
{
serviceHost.Open();
string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine("Listening @ {0}", address);
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
serviceHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
Console.WriteLine();
}
catch (Exception exc)
{
Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
Console.ReadLine();
}
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
#region IHelloWorldService Members
public string SayHello(string name)
{
return string.Format("Hello, {0}", name);
}
#endregion
}
}
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
string addressHttps = String.Format("https://{0}:51222", Dns.GetHostEntry("").HostName);
var wsHttpBinding = new BasicHttpBinding();
wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));
Type endpoint = typeof (IHelloWorldService);
serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");
serviceHost.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName, "nameofsertificate");
serviceHost.Credentials.ClientCertificate.Authentication.RevocationMode = X509RevocationMode.NoCheck;
Uri uri = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");
var smb = new ServiceMetadataBehavior();
smb.HttpsGetEnabled = true;
smb.HttpsGetUrl = uri;
serviceHost.Description.Behaviors.Add(smb);
Console.Out.WriteLine("Mex address " + smb.HttpsGetUrl);
try
{
serviceHost.Open();
string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine("Listening @ {0}", address);
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
serviceHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
Console.WriteLine();
}
catch (Exception exc)
{
Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
Console.ReadLine();
}
}
public static bool ValidateCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach (X509ChainStatus chainStatus in chain.ChainStatus)
{
if (chainStatus.Status == X509ChainStatusFlags.Revoked)
{
return true;
}
}
}
return false;
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
#region IHelloWorldService Members
public string SayHello(string name)
{
return string.Format("Hello, {0}", name);
}
#endregion
}
}
這些示例正在啟動而沒有錯誤,但如果我嘗試創建客戶端,我有兩種不同的情況:
HTTP - 使用地址創建客戶端成功
http://localhost:51222/hello/mex
HTTPS失敗了。 HTTPS的地址是:
https://localhost:51222/hello/mex
HTTPS的錯誤消息是:
下載
https://localhost:51222/hello/mex
。 底層連接已關閉:發送時發生意外錯誤。 身份驗證失敗,因為遠程方已關閉傳輸流。 元數據包含無法解析的引用:https://localhost:51222/hello/mex
。 將HTTP請求發送到https://localhost:51222/hello/mex
發生錯誤。 這可能是由於在HTTPS情況下未使用HTTP.SYS正確配置服務器證書。 這也可能是由客戶端和服務器之間的安全綁定不匹配引起的。 底層連接已關閉:發送時發生意外錯誤。 身份驗證失敗,因為遠程方已關閉傳輸流。 如果在當前解決方案中定義了服務,請嘗試構建解決方案並再次添加服務引用。
我在哪里弄錯了?
我找到了解決方案如何解決這個問題。 所以,正確的服務器代碼是:
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
string addressHttps = String.Format("https://{0}:9010", Dns.GetHostEntry("").HostName);
var wsHttpBinding = new BasicHttpBinding();
wsHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
var serviceHost = new ServiceHost(typeof (HelloWorldService), new Uri(addressHttps));
Type endpoint = typeof (IHelloWorldService);
serviceHost.AddServiceEndpoint(endpoint, wsHttpBinding, "hello");
serviceHost.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName, "sergiiz2");
var smb = new ServiceMetadataBehavior();
smb.HttpsGetEnabled = true;
smb.HttpsGetUrl = new Uri(serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri + "/mex");
serviceHost.Description.Behaviors.Add(smb);
Console.Out.WriteLine(smb.HttpsGetUrl);
try
{
serviceHost.Open();
string address = serviceHost.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine("Listening @ {0}", address);
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
serviceHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("A commmunication error occurred: {0}", ce.Message);
Console.WriteLine();
}
catch (Exception exc)
{
Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
Console.ReadLine();
}
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
#region IHelloWorldService Members
public string SayHello(string name)
{
return string.Format("Hello, {0}", name);
}
#endregion
}
}
以及與證書相關的一些案例: - 生成證書:
makecert -r -pe -n "CN=%hostname%" -b 01/01/2000 -e 01/01/2050 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
添加網址聽
httpcfg set urlacl -u https:// *:9010 / -a D :( A ;; GX ;;; S-1-5-21-1144070942-1563683482-3278297161-1114)
對http.sys說要知道端口9010上的ssl證書
httpcfg set ssl / i 0.0.0.0:9010 / h 8c6e12be5371860adfb84cd2ed2351a900731bb8 / g“{a2c24c79-b0ef-4783-8ed8-d93836fec137}”
並且所有工作都沒有問題。
看看這個答案: 如何以編程方式為自托管WCF服務安裝SSL證書 。
您是否正在使httpsGetUri與您的mex端點地址相同? httpsGetUri用於發布WSDL,而不是為mex端點提供服務。 你應該清楚這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.