摘要
我正在尝试实现受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 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.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace TestService
{
[ServiceContract]
interface ITestService
{
[OperationContract]
[WebInvoke(Method = "POST",RequestFormat = Webmessageformat.Json,UriTemplate = "/PostMsg"
)]
MessageData PostMsg(MessageData msg);
}
[DataContract]
public class MessageData
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Gender { get; set; }
[DataMember]
public int Age { get; set; }
}
}
using System;
namespace TestService
{
class TestService : ITestService
{
public MessageData PostMsg(MessageData msg)
{
Console.WriteLine(string.Format(null,"Recieved Name: {0},Gender:{1},Age:{2}",msg.Name,msg.Gender,msg.Age));
return new MessageData()
{
Name = msg.Name,Gender = msg.Gender,Age = msg.Age + 1
};
}
}
}
客户实施
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},Age{2} ",rtn.Name,rtn.Gender,rtn.Age));
}
}
}
用于创建pfx文件的脚本。
@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."
必需
-
我不想使用IIS,因为我认为它有很多设置。相反,我在“ system.security.Cryptography.X509Certificates”命名空间中使用X509Certificate2类的X509Certificate2方法。 (.NETFramework \ v4.7.2 \ System.dll)
-
服务器和客户端目前在同一台计算机上。
- Windows Defender防火墙的端口已打开。