|
在上一个文章中,传送门,给大家介绍了怎么在配置文件中使用 Kestrel 部署 Https,正好今天有小伙伴稳问到:可以通过代码的方式实现 Kestrel 的 Https 的部署吗?答案是肯定的,我们这次一样去不是多个域名。
在使用代码实现中,我是主要使用到 ListenOptions.UseHttps,我们先看看官方文档怎么说吧,不想看我的可以直接跳转到官方文档,传送门
ListenOptions.UseHttps
将 Kestrel 配置为使用 HTTPS。
ListenOptions.UseHttps 扩展:
UseHttps:将 Kestrel 配置为使用 HTTPS,采用默认证书。 如果没有配置默认证书,则会引发异常。
UseHttps(string fileName)
UseHttps(string fileName, string password)
UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
UseHttps(StoreName storeName, string subject)
UseHttps(StoreName storeName, string subject, bool allowInvalid)
UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
UseHttps(X509Certificate2 serverCertificate)
UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)
ListenOptions.UseHttps 参数:
filename 是证书文件的路径和文件名,关联包含应用内容文件的目录。
password 是访问 X.509 证书数据所需的密码。
configureOptions 是配置 HttpsConnectionAdapterOptions 的 Action。 返回 ListenOptions。
storeName 是从中加载证书的证书存储。
subject 是证书的主题名称。
allowInvalid 指示是否存在需要留意的无效证书,例如自签名证书。
location 是从中加载证书的存储位置。
serverCertificate 是 X.509 证书。
在生产中,必须显式配置 HTTPS。 至少必须提供默认证书。
下面要描述的支持的配置:
无配置
Kestrel 在 http://localhost:5000 和 https://localhost:5001 上进行侦听(如果默认证书可用)。
从配置中替换默认证书
Kestrel 可以使用默认 HTTPS 应用设置配置架构。 从磁盘上的文件或从证书存储中配置多个终结点,包括要使用的 URL 和证书。
架构的注意事项:
- 终结点的名称不区分大小写。 例如,由于再也无法解析标识符“Families”,因此
HTTPS and Https 是等效的。
- 每个终结点都要具备
Url 参数。 此参数的格式和顶层 Urls 配置参数一样,只不过它只能有单个值。
- 这些终结点不会添加进顶层
Urls 配置中定义的终结点,而是替换它们。 通过 Listen 在代码中定义的终结点与在配置节中定义的终结点相累积。
Certificate 部分是可选的。 如果未指定 Certificate 部分,则使用 Certificates efault 中定义的默认值。 如果没有可用的默认值,则使用开发证书。 如果没有默认值,且开发证书不存在,则服务器将引发异常,并且无法启动。
Certificate 部分支持多个证书源。
- 只要不会导致端口冲突,就能在配置中定义任何数量的终结点。
证书源
可以将证书节点配置为从多个源加载证书:
Path 和 Password 用于加载 .pfx 文件。
Path、KeyPath 和 Password 用于加载 .pem/.crt 和 .key 文件。
Subject 和 Store 用于从证书存储中加载。
好了,罗嗦话说完了,我们抽取文档的一部分进行实践
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenAnyIP(5005, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var localhostCert = CertificateLoader.LoadFromStoreCert(
"localhost", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var exampleCert = CertificateLoader.LoadFromStoreCert(
"example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var subExampleCert = CertificateLoader.LoadFromStoreCert(
"sub.example.com", "My", StoreLocation.CurrentUser,
allowInvalid: true);
var certs = new Dictionary<string, X509Certificate2>(
StringComparer.OrdinalIgnoreCase)
{
["localhost"] = localhostCert,
["example.com"] = exampleCert,
["sub.example.com"] = subExampleCert
};
httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
{
if (name is not null && certs.TryGetValue(name, out var cert))
{
return cert;
}
return exampleCert;
};
});
});
});
上面的代码一看就能懂,比较无奈的是官方文档的 SSL 证书是从 证书存储区 里获取的,在实际应用中,明显是不够方便,最好是那种直接写 证书路径 和 密码的,这样才能一目了然嘛,而这里的关键就是 X509Certificate2 这个类了,可以看到,最终是通过检索一个字典返回的,接受的就是这个 X509Certificate2 类,所以我们看看这个类到底是个什么东西,传送门;
这里我们只关注构造函数,下面是官方文档,或者直接 F12 进去看更为直接
构造函数
| X509Certificate2() |
已过时。
初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(Byte[]) |
使用来自字节数组的信息初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(Byte[], SecureString) |
使用一个字节数组和一个密码初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(Byte[], SecureString, X509KeyStorageFlags) |
使用一个字节数组、一个密码和一个密钥存储标志初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(Byte[], String) |
使用一个字节数组和一个密码初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(Byte[], String, X509KeyStorageFlags) |
使用一个字节数组、一个密码和一个密钥存储标志初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(IntPtr) |
使用非托管句柄初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(ReadOnlySpan<Byte>) |
用证书数据初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(ReadOnlySpan<Byte>, ReadOnlySpan<Char>, X509KeyStorageFlags) |
使用证书数据、密码和密钥存储标志初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(SerializationInfo, StreamingContext) |
使用指定的序列化和流上下文信息初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(String) |
使用证书文件名初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(String, ReadOnlySpan<Char>, X509KeyStorageFlags) |
使用一个证书文件名、一个密码和一个密钥存储标志初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(String, SecureString) |
使用一个证书文件名和一个密码初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(String, SecureString, X509KeyStorageFlags) |
使用一个证书文件名、一个密码和一个密钥存储标志初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(String, String) |
使用一个证书文件名和一个用于访问该证书的密码初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(String, String, X509KeyStorageFlags) |
使用一个证书文件名、一个用于访问该证书的密码和一个密钥存储标志初始化 X509Certificate2 类的新实例。
|
| X509Certificate2(X509Certificate) |
使用 X509Certificate 对象初始化 X509Certificate2 类的新实例。
|
直接 F12 也贴出来吧,方便大伙查看
帅气的小伙伴可能已经发现了,里面就存在了一个 直接传入 文件路径 和 密码 作为参数的构造函数,毫无疑问,它就是我们要找的!!!下面我们直接看代码:
Program.cs
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ConfigureHttpsDefaults(listenOptions =>
{
listenOptions.SslProtocols = SslProtocols.Tls13;
});
serverOptions.ListenAnyIP(5209, listenOptions =>
{
listenOptions.UseHttps(httpsOptions =>
{
var test1 = new X509Certificate2("cer\\test1.ysmc.net.cn_server.pfx", "密码1");
var test2 = new X509Certificate2("cer\\test2.ysmc.net.cn_server.pfx", "密码2");
var certs = new Dictionary<string, X509Certificate2>(
StringComparer.OrdinalIgnoreCase)
{
["test1.ysmc.net.cn"] = test1,
["test2.ysmc.net.cn"] = test2
};
httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
{
if (name is not null && certs.TryGetValue(name, out var cert))
{
return cert;
}
return test1;
};
});
});
});
因为是配合了 YARP “食用”的,详情可以查看我前面的文章,传送门,所以不同的域名会反向代理到不同的网站上面,好了,文章到此结束,感谢大佬们的阅读,谢谢!
原文链接:https://www.cnblogs.com/ysmc/p/16721268.html
本文来自博客园,作者:一事冇诚,转载请注明原文链接:https://www.cnblogs.com/ysmc/p/16721268.html
来源:https://www.cnblogs.com/ysmc/p/16721268.html |