Asp.NET Core根据域名响应不同的SSL证书

有时候我们的网站需要根据不同的域名,展示不同的内容,同时域名还得是https协议。在不使用nginx类似代理的情况下,如何动态的响应不同的SSL证书。

需要解决的问题

1.域名证书及需要定制化内容的配置(OEM)

2.程序启动时,加载域名证书

3.请求时,根据域名做出动态响应

关键代码

1.程序启动后,需要在后台任务中读取域名证书的配置加载到内存中

[JobDetail("job_loadhttpscerts", Description = "加载https证书", GroupName = "default", Concurrent = false)]
[PeriodSeconds(1, TriggerId = "trigger_loadhttpscerts", Description = "加载https证书", MaxNumberOfRuns = 1, RunOnStart = true)]
public class LoadHttpsCerts : IJob
{
    private readonly IServiceScopeFactory _scopeFactory;

    public LoadHttpsCerts(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
    {
        var wwwroot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot");
        using var serviceScope = _scopeFactory.CreateScope();

        // 在库中查询出域名和证书配置
        var platConfig = serviceScope.ServiceProvider.GetService<SqlSugarRepository<PlatformConfig>>();


        var list = await platConfig.CopyNew().AsQueryable().ToListAsync(); 

        foreach (var input in list)
        {
            if (!string.IsNullOrEmpty(input.WebUrl) && !string.IsNullOrEmpty(input.SslPwd) && !string.IsNullOrEmpty(input.SslUrl))
            {
                try
                {
                    
                    // 去除域名
                    var uri = new Uri(input.SslUrl);
                    var path = uri.LocalPath;
                    path = path[1..];
                    var sslPath = Path.Combine(wwwroot, path);
                    if (File.Exists(sslPath))
                    {
                        var bytearry = File.ReadAllBytes(sslPath);
                        X509Certificate2 x509Certificate2 = new X509Certificate2(bytearry, input.SslPwd);
                        UtilCertDic.SetCertDic(input.WebUrl, x509Certificate2);
                        Console.WriteLine($"{input.SslUrl}证书加载成功,{sslPath}");
                    }
                    else
                    {
                        Console.WriteLine($"{input.SslUrl}证书找不到,{sslPath}");
                    }
                }
                catch (Exception ex)
                {

                    Console.WriteLine($"{input.SslUrl}证书加载失败,{ex.Message} {ex.StackTrace}");

                }
            }

        }
    }
}

其中UtilCertDic的定义如下


public class UtilCertDic
{
    private static Dictionary<string, X509Certificate2> UtilDic = new Dictionary<string, X509Certificate2>();

    private static object lockdic = new object();

    public static bool GetCertDic(string key, out X509Certificate2 certificate2)
    {
        return UtilDic.TryGetValue(key, out certificate2);
    }
    /// <summary>
    /// 新增
    /// </summary>
    /// <param name="key"></param>
    /// <param name="x509Certificate2"></param>
    /// <param name="delCert"></param>
    public static void SetCertDic(string key, X509Certificate2 x509Certificate2, string delCert = null)
    {
        lock (lockdic)
        {
            if (delCert != null)
            {
                UtilDic.Remove(delCert);
            }
            if (UtilDic.ContainsKey(key))
            {
                UtilDic.Remove(key);
            }
            UtilDic.Add(key, x509Certificate2);
        }
    }
}

 2.请求时根据域名做出动态响应

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenAnyIP(443, listenOptions =>
    {
        string rootUrl = AppDomain.CurrentDomain.BaseDirectory + Path.DirectorySeparatorChar + "ssl";

        X509Certificate2 defaultmodel = new X509Certificate2(rootUrl + Path.DirectorySeparatorChar + "xxxx.pfx", "Aa123456");

        listenOptions.UseHttps(httpsOptions =>
        {
            

            httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
            {
                if (name is not null && UtilCertDic.GetCertDic(name, out var cert))
                {
                    return cert;
                }

                return defaultmodel;
            };
        });

        
    });
});

下一步,实现免费证书自动续期

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值