Сводка
Я пытаюсь внедрить службу RESTFul WCF, защищенную SSL, но произошла следующая ошибка и не удалось установить связь.
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}, Gender:{1}, 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, потому что я думаю, что есть много настроек с ним. Вместо этого я использую метод X509Certificate2 класса X509Certificate2 в пространстве имен «System.Security.Cryptography.X509Certificates». (.NETFramework \ v4.7.2 \ System.dll)
В настоящий момент сервер и клиент находятся на одном компьютере.
- Порты брандмауэра защитника Windows
Некоторые изображения для понимания того, что я делаю.
https://i.stack.imgur.com/MCFl9.png
https://i.stack.imgur.com/DgNid.png