这是我使用了一段时间的解决方案。
这里的关键是创建自己的自定义 Https 证书定位器
并使用它根据您的
环境。例如,在本地使用默认值是有意义的
localhost 由 Visual Studio 工具创建的 HTTPS 证书。在
您可能需要根据其他环境识别正确的证书
一些标准,例如它的通用名称。
覆盖CreateServiceInstanceListeners 无状态服务中的CreateServiceInstanceListeners 操作以配置https 端口。这也是您提供自定义 HttpsCertificateLocator 实现的地方。
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
listenOptions.UseHttps(new HttpsCertificateLocator().GetHttpsCertificateFromStore());
});
})
示例 HTTPS 证书定位器
public class HttpsCertificateLocator : BaseHttpsCertificateLocator, IHttpsCertificateLocator
{
private readonly string[] _cNsToTryInOrderOfPriority;
private readonly bool _isDevelopment;
private const string Development = nameof(Development);
public HttpsCertificateLocator(string environmentName = null, string[] cNsToTryInOrderOfPriority = null)
{
_cNsToTryInOrderOfPriority = cNsToTryInOrderOfPriority ?? CommonCertificates.Intranet.DefaultCNs;
var environment = string.IsNullOrWhiteSpace(environmentName)
? (System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? Development)
: environmentName;
_isDevelopment = string.Compare(environment, Development, StringComparison.OrdinalIgnoreCase) == 0;
}
/// <summary>
/// If environment is Development, finds and returns the ASP .NET Core HTTPS development certificate in development environment.
/// In other developments, returns a HTTPS certificate that is assumed installed on all Service Fabric cluster nodes
/// </summary>
public X509Certificate2 GetHttpsCertificateFromStore(bool httpsMandatory = true)
{
if (_isDevelopment)
{
return ReturnDevCertificate(httpsMandatory);
}
using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
var certCollection = store.Certificates;
foreach (var subjectName in _cNsToTryInOrderOfPriority)
{
var matchingCerts = certCollection.Find(X509FindType.FindBySubjectDistinguishedName, subjectName, true);
if (matchingCerts.Count > 0)
{
return EnsureMostRecentCertificate(matchingCerts, subjectName, httpsMandatory);
}
}
return EnsureMostRecentCertificate(
new X509Certificate2Collection(),
_cNsToTryInOrderOfPriority.LastOrDefault() ?? "<NONE SPECIFIED>",
httpsMandatory);
}
}
}
以上代码继承自BaseHttpsCertificateLocator。它提供了额外的功能来定位默认的开发localhost HTTPs 证书。它还具有查找最新证书的代码(开始滚动证书时必须处理的事情)。
public abstract class BaseHttpsCertificateLocator
{
protected X509Certificate2 ReturnDevCertificate(bool httpsMandatory)
{
// Note: AspNet Core should auto generate/install this X509 cert on dev PCs
const string aspNetHttpsOid = "1.3.6.1.4.1.311.84.1.1";
const string cnLocalhost = "CN=localhost";
using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
var certCollection = store.Certificates;
var currentCerts = certCollection.Find(X509FindType.FindByExtension, aspNetHttpsOid, true);
var matchingCerts = currentCerts.Find(X509FindType.FindByIssuerDistinguishedName, cnLocalhost, true);
return EnsureMostRecentCertificate(matchingCerts, cnLocalhost, httpsMandatory);
}
}
protected X509Certificate2 EnsureMostRecentCertificate(
X509Certificate2Collection marchingCerts,
string cnName,
bool httpsMandatory)
{
if (marchingCerts.Count == 0)
{
return httpsMandatory
? throw new SecurityException($"Unable to locate HTTPS X509 cert `{cnName}`")
: default(X509Certificate2);
}
if (marchingCerts.Count > 1)
{
return marchingCerts.Cast<X509Certificate2>().OrderByDescending(x => x.NotAfter).First();
}
return marchingCerts[0];
}
}