C# 受SSL保护的RESTFul WCF自托管服务 总结
我正在尝试实现受SSL保护的RESTFul WCF服务,但出现以下错误,通信失败C# 受SSL保护的RESTFul WCF自托管服务 总结,c#,rest,wcf,self-hosting,webhttpbinding,C#,Rest,Wcf,Self Hosting,Webhttpbinding,我正在尝试实现受SSL保护的RESTFul WCF服务,但出现以下错误,通信失败 making the HTTP request to ‘https://123.123.123.123:5000/TestService/PostMsg’. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could a
making the HTTP request to ‘https://123.123.123.123:5000/TestService/PostMsg’. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server. on some customers machines.
有人能帮我吗?
致意
尝试过的事情:
我成功地在没有SSL保护的情况下进行了通信
代码
服务实现
using System;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Web;
namespace TestService
{
class Program
{
static WebServiceHost host;
static void Main()
{
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
Uri uri = new Uri("https://localhost:5000/TestService");
host = new WebServiceHost(typeof(TestService));
ServiceEndpoint se = host.AddServiceEndpoint(typeof(ITestService), binding, uri);
var behavior = new WebHttpBehavior();
behavior.FaultExceptionEnabled = false;
behavior.HelpEnabled = true;
behavior.DefaultOutgoingRequestFormat = WebMessageFormat.Json;
behavior.DefaultOutgoingResponseFormat = WebMessageFormat.Json;
se.EndpointBehaviors.Add(behavior);
ServiceDebugBehavior debug = host.Description.Behaviors.Find<ServiceDebugBehavior>();
debug.IncludeExceptionDetailInFaults = true;
ServiceMetadataBehavior metad = new ServiceMetadataBehavior();
metad.HttpGetEnabled = true;
metad.HttpsGetEnabled = true;
host.Description.Behaviors.Add(metad);
var certificate = new X509Certificate2(@"D:\Work\TestService\ServerCert1.pfx", "paswd", X509KeyStorageFlags.UserKeySet);
host.Credentials.ServiceCertificate.Certificate = certificate;
host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
host.Open();
Console.WriteLine(string.Format(null, "URL : {0}", uri.ToString()));
Console.WriteLine("Press <ENTER> to terminate");
Console.ReadLine();
host.Close();
}
}
}
using System;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Web;
using TestService;
namespace TestClient
{
public partial class Form1 : Form
{
WebChannelFactory<ITestService> cf = null;
ITestService channel = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
listBox1.HorizontalScrollbar = true;
Uri uri = new Uri("https://123.123.123.123:5000/TestService");
EndpointAddress endpointAddress = new EndpointAddress(uri);
cf = new WebChannelFactory<ITestService>(uri);
WebHttpBinding binding = cf.Endpoint.Binding as WebHttpBinding;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Mode = WebHttpSecurityMode.Transport;
var behavior = new WebHttpBehavior();
behavior.FaultExceptionEnabled = false;
behavior.HelpEnabled = true;
behavior.DefaultOutgoingRequestFormat = WebMessageFormat.Json;
behavior.DefaultOutgoingResponseFormat = WebMessageFormat.Json;
cf.Endpoint.Behaviors.Add(behavior);
var clientCertificate = new X509Certificate2(@"D:\Work\TestService\ServerCert1.pfx", "pswd", X509KeyStorageFlags.UserKeySet);
cf.Credentials.ClientCertificate.Certificate = clientCertificate;
cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
channel = cf.CreateChannel();
}
private void button1_Click(object sender, EventArgs e)
{
MessageData msg = new MessageData()
{
Name = "Taro",
Gender = 1,
Age = 3
};
MessageData rtn = channel.PostMsg(msg);
listBox1.Items.Insert(0, string.Format("Name:{0}, Gender:{1}, Age{2} ", rtn.Name, rtn.Gender, rtn.Age));
}
}
}
客户端实现
using System;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Web;
namespace TestService
{
class Program
{
static WebServiceHost host;
static void Main()
{
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
Uri uri = new Uri("https://localhost:5000/TestService");
host = new WebServiceHost(typeof(TestService));
ServiceEndpoint se = host.AddServiceEndpoint(typeof(ITestService), binding, uri);
var behavior = new WebHttpBehavior();
behavior.FaultExceptionEnabled = false;
behavior.HelpEnabled = true;
behavior.DefaultOutgoingRequestFormat = WebMessageFormat.Json;
behavior.DefaultOutgoingResponseFormat = WebMessageFormat.Json;
se.EndpointBehaviors.Add(behavior);
ServiceDebugBehavior debug = host.Description.Behaviors.Find<ServiceDebugBehavior>();
debug.IncludeExceptionDetailInFaults = true;
ServiceMetadataBehavior metad = new ServiceMetadataBehavior();
metad.HttpGetEnabled = true;
metad.HttpsGetEnabled = true;
host.Description.Behaviors.Add(metad);
var certificate = new X509Certificate2(@"D:\Work\TestService\ServerCert1.pfx", "paswd", X509KeyStorageFlags.UserKeySet);
host.Credentials.ServiceCertificate.Certificate = certificate;
host.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
host.Open();
Console.WriteLine(string.Format(null, "URL : {0}", uri.ToString()));
Console.WriteLine("Press <ENTER> to terminate");
Console.ReadLine();
host.Close();
}
}
}
using System;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.ServiceModel.Web;
using TestService;
namespace TestClient
{
public partial class Form1 : Form
{
WebChannelFactory<ITestService> cf = null;
ITestService channel = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
listBox1.HorizontalScrollbar = true;
Uri uri = new Uri("https://123.123.123.123:5000/TestService");
EndpointAddress endpointAddress = new EndpointAddress(uri);
cf = new WebChannelFactory<ITestService>(uri);
WebHttpBinding binding = cf.Endpoint.Binding as WebHttpBinding;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
binding.Security.Mode = WebHttpSecurityMode.Transport;
var behavior = new WebHttpBehavior();
behavior.FaultExceptionEnabled = false;
behavior.HelpEnabled = true;
behavior.DefaultOutgoingRequestFormat = WebMessageFormat.Json;
behavior.DefaultOutgoingResponseFormat = WebMessageFormat.Json;
cf.Endpoint.Behaviors.Add(behavior);
var clientCertificate = new X509Certificate2(@"D:\Work\TestService\ServerCert1.pfx", "pswd", X509KeyStorageFlags.UserKeySet);
cf.Credentials.ClientCertificate.Certificate = clientCertificate;
cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
channel = cf.CreateChannel();
}
private void button1_Click(object sender, EventArgs e)
{
MessageData msg = new MessageData()
{
Name = "Taro",
Gender = 1,
Age = 3
};
MessageData rtn = channel.PostMsg(msg);
listBox1.Items.Insert(0, string.Format("Name:{0}, Gender:{1}, Age{2} ", rtn.Name, rtn.Gender, rtn.Age));
}
}
}
必需的
- 我不想使用IIS,因为我认为它有很多设置。相反,我在“System.Security.Cryptography.X509Certificates”名称空间中使用X509Certificate2类的X509Certificate2方法。(.NETFramework\v4.7.2\System.dll)
- 此时,服务器和客户端位于同一台计算机上
- Windows defender防火墙的端口已打开
使用证书保护通信需要使用以下命令将证书绑定到特定的计算机端口 Netsh http add sslcert ipport=0.0.0.0:5000证书哈希= 0102030405060708090A0B0C0D0E0F10111121314应用程序ID= appid={00112233-4455-6677-8899-AABBCCDDEEFF}
当我们设置站点绑定时,此功能在IIS中自动完成。 关于使用证书认证客户,请参阅以下官方文件。
我们通常需要注意两点 1.我们应该确保服务证书和客户端证书都具有客户端身份验证和服务器身份验证的目的。 服务器身份验证(1.3.6.1.5.5.7.3.1)
客户验证(1.3.6.1.5.5.7.3.2) 2.我们最好在Dotnet framwork4.6.2上构建该项目,因为读取使用PowerShell证书创建的证书的私钥时出现问题。 如果有什么我能帮忙的,请随时告诉我。
1.我了解到,根据用途的不同,有几种类型的证书。现在,我将研究如何实现它。我已经安装了Dotnet Framwork 4.6.2。谢谢。:)在服务器源代码中X509Certificate2方法的第一个参数中,是否要指定客户端证书文件(使用1.3.6.1.5.5.7.3.2创建)?在客户端源代码中,是否要指定服务器证书(使用1.3.6.1.5.5.7.3.1创建)?是的,这些证书应添加两个预期用途。我建议您使用Powershell创建证书,因为通过以下命令创建的证书默认包含两个预期用途。新的自签名证书-DnsName“mycomputername”-CertStoreLocation“cert:\LocalMachine\My”
@echo ----------------------------------------------
@echo Script for creating self certificate
@echo ----------------------------------------------
@set "TOOL_DIR=E:\Windows Kits\10\bin\10.0.18362.0\x86"
@if not exist "%TOOL_DIR%" (
@echo Tools do not exists. %TOOL_DIR%
@goto ERROR_EXIT
)
@set "PATH=%TOOL_DIR%;%PATH%"
@set "WORK_DIR=D:\Work\TestService"
@if not exist %WORK_DIR% (
@echo Work folder does not exist. %WORK_DIR%
@goto ERROR_EXIT
)
cd /d %WORK_DIR%
@openfiles > NUL 2>&1
@if NOT %ERRORLEVEL% EQU 0 (
@echo It is not being executed as an administor.
goto ERROR_EXIT
)
@SET /P ANS="Create a certificate file. Are you sure (Y / N)?"
@if /i %ANS% NEQ y if /i %ANS% NEQ Y goto ERROR_EXIT
del %WORK_DIR%\*.*
@echo;
@echo Create Self-Signed Certificate
makecert -n "CN=ServerCN1" -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv ServerCert1.pvk ServerCert1.cer -cy authority -b 11/06/2019 -e 12/31/2019
@echo;
@echo Create Software Publisher Certificate File
cert2spc ServerCert1.cer ServerCert1.spc
@echo;
@echo Create Personal Information Exchange File
pvk2pfx -pvk ServerCert1.pvk -spc ServerCert1.spc -po pswd -pfx ServerCert1.pfx -f
@echo;
:ERROR_EXIT
@SET /P ANS="Finished."
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Cert