Я пытаюсь установить связь WCF для работы через соединение TLS. Я использую Mono 5.20.1.19 в Ubuntu 18.04, хотя я надеюсь, что решение будет работать и в Windows.
Рассмотрим базовый интерфейс, подобный этому:
IExample.cs:
using System;
using System.ServiceModel;
namespace Example
{
[ServiceContract]
public interface IExample
{
[OperationContract]
string Greet();
}
}
У меня есть сервер, который настраивает ServiceHost для реализации интерфейса:
Server.cs:
using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Security.Cryptography.X509Certificates;
namespace Example
{
public class ExampleImpl : IExample
{
public string Greet()
{
Console.WriteLine("Greet() called");
return "Hello!";
}
}
public static class Program
{
public static void Main(string[] args)
{
using(var host = new ServiceHost(typeof(ExampleImpl), new Uri("net.tcp://localhost:5555"))){
var binding = new NetTcpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
binding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;
host.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySubjectName,
"server");
host.AddServiceEndpoint(typeof(IExample), binding, "Example");
host.Open();
Console.WriteLine("listening at :5555");
Console.WriteLine("Press Enter to end the program");
Console.ReadLine();
}
}
}
}
Обратите внимание, что SecurityMode.Transport
указано для NetTcpBinding и TcpClientCredentialType.Certificate
для типа учетных данных клиента. Я также указываю сертификат, который я установил в хранилище сертификатов My
, в дополнение к закрытому ключу для сертификата.
Теперь клиент:
Client.cs:
using System;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace Example
{
public static class Program
{
public static void Main(string[] args)
{
var binding = new NetTcpBinding(SecurityMode.None);
var factory = new ChannelFactory<IExample>(binding, new EndpointAddress("net.tcp://localhost:5555/Example"));
var obj = factory.CreateChannel();
Console.WriteLine(obj.Greet());
}
}
}
Обратите внимание, что в клиенте режим безопасности NetTcpBinding установлен на None
, а сертификат клиента не указан.
Мы можем построить две программы:
$ csc Server.cs IExample.cs
Microsoft (R) Visual C# Compiler version 2.8.2.62916 (2ad4aabc)
Copyright (C) Microsoft Corporation. All rights reserved.
$ csc Client.cs IExample.cs
Microsoft (R) Visual C# Compiler version 2.8.2.62916 (2ad4aabc)
Copyright (C) Microsoft Corporation. All rights reserved.
Теперь, если мы запустим Server.exe, оставим его открытым, а затем в другом сеансе запустим Client.exe, сервер напечатает сообщение Greet() called
, а клиент напечатает Hello!
.
Я путаюсь с тем, почему соединение установлено успешно. Я ожидаю, что, поскольку привязка сервера установлена на Transport
, то для этого требуется соединение TLS; однако, похоже, что TLS не используется, так как не указывается сертификат клиента.
Как мне изменить серверную часть кода, чтобы требовать соединения TLS?