Проблема в том, что КОРНЕВОЙ ЦС, который должен проверять сертификат с сервера, не может присутствовать в корневом хранилище доверенных сертификатов системы клиента. Он должен быть загружен во время выполнения.
Окончательная реализация реализована под Linux, но она также не работает в Windows.
Это работает, только если Я добавляю корневой центр сертификации в системный центр сертификации. В остальных случаях я всегда получаю исключение.
Корневой ЦС не имеет зависимостей от другого ЦС. Это отдельный сертификат.
Я использую .net core 6
.
Класс UserManagemenClient генерируется автоматически.
Код: Выделить всё
public partial class UserManagementClient : System.ServiceModel.ClientBase, ConsoleApp7.UserManagementService.IUserManagement
Программа вызывает следующее исключение.
System.AggregateException: произошла одна или несколько ошибок. (Не удалось установить доверительные отношения для безопасного канала SSL/TLS с полномочиями «gui.net:8443».)
---> System.ServiceModel.Security.SecurityNegotiationException: не удалось установить доверительные отношения для SSL/TLS. безопасный канал с полномочиями 'gui.net:8443'.
---> System.Net.Http.HttpRequestException: соединение SSL не может быть установлено, см. внутреннее исключение.
---> System. Security.Authentication.AuthenticationException: удаленный сертификат недействителен из-за ошибок в цепочке сертификатов: UntrustedRoot
в System.Net.Security.SslStream.SendAuthResetSignal(сообщение ProtocolToken, исключение ExceptionDispatchInfo)
в System.Net. Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
в System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](адаптер TIOAdapter, логическое значение полученияFirst, Byte[] reAuthenticationData, логическое значение isApm)
в System.Net. Security.SslStream.ProcessAuthenticationWithTelemetryAsync(Boolean isAsync, Boolean isApm, CancellationToken cancelToken)
в System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, запрос HttpRequestMessage, логический async, поток потока, CancellationToken cancelToken)
- --- Конец внутренней трассировки стека исключений ---
в System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, запрос HttpRequestMessage, Boolean async, Stream поток, CancellationToken cancelToken)
в System.Net. Http.HttpConnectionPool.ConnectAsync(запрос HttpRequestMessage, Boolean async, CancellationToken cancelToken)
в System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(запрос HttpRequestMessage, Boolean async, CancellationToken cancelToken)
в System.Net.Http. HttpConnectionPool.AddHttp11ConnectionAsync(запрос HttpRequestMessage)
в System.Threading.Tasks.TaskCompletionSourceWithCancellation
Код: Выделить всё
1.WaitWithCancellationAsync(CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken) at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken) at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken) at System.ServiceModel.Channels.HttpChannelFactory--- Конец внутренней трассировки стека исключений ---
at System.Runtime.AsyncResult.End[TAsyncResult]( Результат IAsyncResult)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(результат SendAsyncResult)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, результат IAsyncResult)at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.c__DisplayClass1_0.b__0(IAsyncResult asyncResult)
Здесь используется образец
Код: Выделить всё
public void Test2(string url)
{
var httpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None)
{
Name = "UserManagementServiceSoapBinding"
};
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
httpBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
if (uri.ToLower().Contains("https"))
httpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
var endpointAddress = new EndpointAddress(uri);
var client = new UserManagementClient(httpBinding, endpointAddress);
client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
client.ClientCredentials.ServiceCertificate.Authentication.CustomCertificateValidator = new CustomRootCertificateValidator(rootCaCertPath);
try
{
var result = client.checkOTPAsync("aaa", new[]
{
"", "", ""
}).Result;
}
catch (Exception e)
{
Console.WriteLine(e);
return;
}
Console.WriteLine("Worked");
}
}
public class CustomRootCertificateValidator : X509CertificateValidator
{
private X509Certificate2 _rootCertificate;
public CustomRootCertificateValidator(string rootCertificatePath)
{
_rootCertificate = new X509Certificate2(rootCertificatePath);
}
public override void Validate(X509Certificate2 certificate)
{
if (certificate == null)
{
throw new ArgumentNullException(nameof(certificate));
}
var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.Add(_rootCertificate);
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
bool isValid = chain.Build(certificate);
if (!isValid || chain.ChainElements[^1].Certificate.Thumbprint != _rootCertificate.Thumbprint)
{
throw new SecurityTokenValidationException("La validazione del certificato è fallita. Il certificato radice non è attendibile.");
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/790 ... ertificati
Мобильная версия