为什么使用der证书和PEM私钥加密的SignalR服务器无法成功连接

问题描述 投票:0回答:1

服务器端代码Program.cs

using SignalRService.Common;
using SignalRService.Hubs;
using SignalRService.Providers;
using SignalRService.Services;
using Microsoft.AspNetCore.SignalR;

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseWindowsService(options =>
{
    options.ServiceName = "SignalR Server Service";
});
builder.WebHost.UseKestrel(options =>
{
    options.ListenAnyIP(12316, config =>
    {
        var certificateMgr = new CertificateMgr();
        var certificate = certificateMgr.GetCertificate();
        if (certificate != null)
        {
            config.UseHttps(certificate);
        }
    });
});
builder.Services.AddCors(options =>
{
    options.AddPolicy(name: "AllowAll", builder =>
        builder.AllowAnyOrigin()
               .AllowAnyMethod()
               .AllowAnyHeader());
});
builder.Services.AddSignalR(options =>
{
    options.EnableDetailedErrors = true;
});
builder.Services
    .AddSingleton<IUserIdProvider, UserIdProvider>()
    .AddHostedService<ServerService>();

var app = builder.Build();
app.UseRouting();
app.UseCors("AllowAll");
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ProxyHub>("proxyHub").RequireCors("AllowAll");
});
await app.RunAsync();

SignalR 服务器端的CertificateMgr.cs

namespace SignalRService.Common
{
    public class PasswordFinder : IPasswordFinder
    {
        private string password;
        public PasswordFinder(string pwd) => password = pwd;
        public char[] GetPassword() => password.ToCharArray();
    }
    public class CertificateMgr
    {
        public string _certPath = "C:\\Working Folder\\certificateFile.der";
        public string _keyPath = "C:\\Working Folder\\privateKey.pem";
        public X509Certificate2? GetCertificate()
        {
            string fileExtension = Path.GetExtension(_certPath);
            if (string.Equals(fileExtension, ".pfx", StringComparison.OrdinalIgnoreCase))
            {
                return new X509Certificate2(_certPath, "123123");
            }
            else
            {
                StreamReader sr = new StreamReader(_keyPath);
                string privateKeyPass = "123123";
                var pf = new PasswordFinder(privateKeyPass);
                PemReader pr = new PemReader(sr, pf);
                AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
                RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
                using (RSA rsa = RSA.Create())
                {
                    rsa.ImportParameters(rsaParameters);
                    X509Certificate2 certificate = new X509Certificate2(_certPath);
                    certificate = certificate.CopyWithPrivateKey(rsa);
                    return certificate;
                }
            }
        }
    }
}

客户端代码Client.cs

using SignalRClient.Common;
using Microsoft.AspNetCore.SignalR.Client;
using System;
using System.Data.SqlTypes;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

namespace SignalRClient.Connections
{
    public interface IProxyClient
    {
        Task Initialize();
        Task HubConnection_StartAsync();
        Task HubConnection_StopAsync();
    }
    public class SignalRClient : IProxyClient
    {
        private HubConnection? _hubConnection;
        public Task Initialize()
        {
            Console.WriteLine($"Initialize");
            return Task.CompletedTask;
        }
        public async Task HubConnection_StartAsync()
        {
            _hubConnection = new HubConnectionBuilder()
                .WithUrl("https:10.224.10.10:12316/proxyHub", (options) =>
                {
                    options.HttpMessageHandlerFactory = (handler) =>
                    {
                        if (handler is HttpClientHandler clientHandler)
                        {
                            clientHandler.ServerCertificateCustomValidationCallback += CheckCertificateCallback;
                        }
                        return handler;
                    };
                })
                .WithAutomaticReconnect(new RandomRetryPolicy())
                .Build();
            _hubConnection.Closed += HubConnection_Closed;
            _hubConnection.Reconnecting += HubConnection_Reconnecting;
            _hubConnection.Reconnected += HubConnection_Reconnected;
            _hubConnection.On<string>("MessageToClient", HubConnection_Received);
            try
            {
                await _hubConnection.StartAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private bool CheckCertificateCallback(HttpRequestMessage message, X509Certificate2? certificate, X509Chain? chain, SslPolicyErrors errors)
        {
            return true;
        }

        public async Task HubConnection_StopAsync()
        {
            if (_hubConnection != null)
            {
                await _hubConnection.StopAsync();
                _hubConnection = null;
            }
        }
        public async Task SendMessageToServer(string message)
        {
            if (_hubConnection != null
                && _hubConnection.State == HubConnectionState.Connected)
            {
                await _hubConnection.InvokeAsync("MessageFromClient", message);
            }
        }
        private Task HubConnection_Closed(Exception? exception)
        {
            Console.WriteLine($"Closed {exception?.Message}");
            return Task.CompletedTask;
        }
        private Task HubConnection_Reconnecting(Exception? exception)
        {
            Console.WriteLine($"Reconnecting {exception?.Message}");
            return Task.CompletedTask;
        }
        private Task HubConnection_Reconnected(string? arg)
        {
            Console.WriteLine($"{arg}");
            return Task.CompletedTask;
        }
        private void HubConnection_Received(string message)
        {
            DateTime dateTime = DateTime.UtcNow;
            Console.WriteLine($"Received {message}: " + dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff"));
        }
    }
}

上面的代码运行时,出现了问题。如果服务器端使用pfx格式的证书,客户端可以执行到CheckCertificate回调函数中,客户端就可以连接到服务器端了;如果服务端使用der证书和pem私钥,则只有服务端能够成功运行,客户端无法执行CheckVerifieCallback函数。运行StartAsync后报错。

c# ssl-certificate signalr signalr.client
1个回答
0
投票

错误结果在这里,有人知道吗?

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.IO.IOException:  Received an unexpected EOF or 0 bytes from the transport stream.
   at System.Net.Security.SslStream.<FillHandshakeBufferAsync>g__InternalFillHandshakeBufferAsync|189_0[TIOAdapter](TIOAdapter adap, ValueTask`1 task, Int32 minSize)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage request)
   at 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.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.Internal.AccessTokenHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.Internal.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.NegotiateAsync(Uri url, HttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.GetNegotiationResponseAsync(Uri uri, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.SelectAndStartTransport(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsyncCore(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection.StartAsync(TransferFormat transferFormat, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.Connections.Client.HttpConnectionFactory.ConnectAsync(EndPoint endPoint, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncCore(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsyncInner(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.SignalR.Client.HubConnection.StartAsync(CancellationToken cancellationToken)
© www.soinside.com 2019 - 2024. All rights reserved.