不知道我是否愚蠢。
使用 NET 6,我有一段代码可以在我指定的端口上启动 Kestrel,并使用配置中指定的 SSL 证书。基本上这在开发机器和 UAT 服务器上工作得很好,因为它们有本地主机的开发证书,并且在 UAT 上,当外部调用站点时会加载正确的证书。
当我将其移至生产环境时,如果没有开发证书,它将无法启动并显示“无法配置 HTTPS 端点。未指定服务器证书,并且找不到默认开发人员证书...”错误。我通过删除 UAT 上的开发者证书来验证原因,然后它无法启动,以同样的方式,当我重新安装证书时,它再次启动正常。
对我来说,这是有道理的,因为它试图侦听包括环回在内的所有 IP 地址,但是我可以做些什么,以便无需在生产服务器上安装开发证书即可启动它,这似乎是一个可怕的黑客攻击?
WebApplicationBuilder builder = WebApplication.CreateBuilder(options);
builder.Host.UseWindowsService(options => options.ServiceName = "Windows Kestrel Server");
builder.WebHost.ConfigureKestrel(serverOptions =>
{
int Port = builder.Configuration.GetValue<int>("Port");
serverOptions.ListenAnyIP(Port, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
{
string? StoreName = builder.Configuration.GetSection("CertificateStore").Value;
string? CertName = builder.Configuration.GetSection("CertificateName").Value;
if (StoreName == null)
StoreName = "My";
if (string.IsNullOrEmpty(CertName))
CertName = clientHelloInfo.ServerName;
X509Certificate2? Cert = null;
try
{
Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.LocalMachine, allowInvalid: false);
}
catch { };
try
{
if (Cert == null)
Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.CurrentUser, allowInvalid: false);
}
catch { };
return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions { ServerCertificate = Cert});
}, state: null!);
});
});
});
我尝试了各种方法将证书设置为配置中指定的证书,但它们似乎都遇到了同样的基本问题
我尝试在配置中添加默认值,但没有成功,因为我使用的是 builder.WebHost.ConfigureKestrel,并且我尝试在 serverOptions.ListenAnyAPI 中配置默认值,但失败了因为它运行得太晚了。
我需要做的就是在配置监听器之前在ConfigureKestral中配置serverOptions.ConfigureHttpsDefaults!
我希望这可以帮助其他遇到类似部署问题的人。
WebApplicationBuilder builder = WebApplication.CreateBuilder(options);
builder.Host.UseWindowsService(options => options.ServiceName = "Windows Kestrel Server");
builder.WebHost.ConfigureKestrel(serverOptions =>
{
int Port = builder.Configuration.GetValue<int>("Port");
// IPGlobalProperties IPP = IPGlobalProperties.GetIPGlobalProperties();
serverOptions.ConfigureHttpsDefaults(configureOptions =>
{
string? StoreName = builder.Configuration.GetSection("CertificateStore").Value;
string? CertName = builder.Configuration.GetSection("CertificateName").Value;
if (StoreName == null)
StoreName = "My";
if (string.IsNullOrEmpty(CertName))
CertName = "localhost";
X509Certificate2? DefaultCert = null;
try
{
DefaultCert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.LocalMachine, allowInvalid: false);
}
catch { };
try
{
if (DefaultCert == null)
DefaultCert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.CurrentUser, allowInvalid: false);
}
catch { };
configureOptions.ServerCertificate = DefaultCert;
});
serverOptions.ListenAnyIP(Port, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
listenOptions.UseHttps((stream, clientHelloInfo, state, cancellationToken) =>
{
string? CertName = builder.Configuration.GetSection("CertificateName").Value;
string? StoreName = builder.Configuration.GetSection("CertificateStore").Value;
if (StoreName == null)
StoreName = "My";
if (string.IsNullOrEmpty(CertName))
CertName = clientHelloInfo.ServerName;
X509Certificate2? Cert = null;
try
{
Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.LocalMachine, allowInvalid: false);
}
catch { };
try
{
if (Cert == null)
Cert = CertificateLoader.LoadFromStoreCert(CertName, StoreName, StoreLocation.CurrentUser, allowInvalid: false);
}
catch { };
return new ValueTask<SslServerAuthenticationOptions>(new SslServerAuthenticationOptions { ServerCertificate = Cert});
}, state: null!);
});
});
});