使用代码在iis中动态为某个站点绑定ssl证书

本文介绍了如何使用C#动态地为IIS站点绑定SSL证书,详细阐述了从理解SSL证书购买流程,到利用ServerManager类操作IIS,特别是关键的bindingInformation、certificateHash和certificateStoreName参数的含义。在最新补充中,针对Windows Server 2016系统上遇到的绑定异常问题,作者给出了调试和解决办法,涉及到证书存储位置的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于业务需要,上头发布任务,需要做一个动态绑定ssl证书的小功能,由于之前比较少接触ssl证书相关方面的知识,所以一时卡住了,不知道如何下手,所以第一反应就是找度娘(我知道这是个不好的习惯,见谅见谅),不知道是我查找的方式不对还是确实比较少人发布类似的文章,我百度了很久,很难找到相匹配的资料。这时我就想,我甚至都不知道这个ssl证书是怎么申请,申请后他会提供什么给我,这样就想做一个东西,也太不切实际了,是否应该先去了解下整个ssl证书申请和购买的流程,这样也许会有提供好的思路,果不其然,了解到购买ssl证书之后他会提供对应的文件(主要用到的是里面的.pfx文件)以及一个证书秘钥。既然他提供了这些东西给你,肯定会用在什么地方。

这里我使用的语言是c#,通过ServerManager类对iis进行相对应的操作(包括建立站点,程序池,绑定域名之类,这里不详细解释,网上有很多这方面的资料),我就想既然可以手动在iis创建域名并绑定ssl证书,那应该也有对应的实现方法,果然找到了里面的一个方法,贴上代码先

ServerManager sm = new ServerManager();
string bindingInformation = "*:" + port + ":" + bindingDomainName;
sm.Sites[webName].Bindings.Add(bindingInformation, certificateHash, certificateStoreName);

bindingInformation应该不用解释,一眼就看到是绑定的端口和域名, certificateHashcertificateStoreName又是什么呢?certificateHash参数类型是byte[],而certificateStoreName参数类型是string,通过直接百度翻译得到的结果是证书散列证书,正在思考他们的来源时,突然想到购买ssl证书之后提供给我们的相关文件和秘钥,应该和这里大有关联,通过查询一些资料,得知certificateHash(证书散列)是通过.pfx文件获取而来的,而certificateStoreName则是证书名称,这里贴上完整的代码

/// <summary>
/// 增加绑定域名(ssl)
/// </summary>
/// <param name="webName">站点名称</param>
/// <param name="port">端口</param>
/// <param name="bindingDomainName">绑定域名</param>
public void AddHostHeaderSSL(string webName, string port, string bindingDomainName)
{
    //**pfxPath**是指提供给你的.pfx文件的路径,购买ssl之后他会提供给你相关的文件,里面有多个文件
    //一般包含apache文件夹,iis文件夹,nginx文件夹,我使用的是iis部署,所以.pfx文件在iis文件夹里面
    //**certPwd**是指购买ssl之后提供给你的秘钥
    string pfx = Directory.GetFiles(pfxPath, "*.pfx", SearchOption.AllDirectories).FirstOrDefault();
    var store = new X509Store(StoreName.AuthRoot, StoreLocation.LocalMachine);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

    var certificate = new X509Certificate2(pfx, certPwd, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
    store.Add(certificate);
    store.Close();
    var certificateStoreName = store.Name;              //绑定的证书名称
    var certificateHash = certificate.GetCertHash();    //证书内容

    ServerManager sm = new ServerManager();
    string bindingInformation = "*:" + port + ":" + bindingDomainName;
    sm.Sites[webName].Bindings.Add(bindingInformation, certificateHash, certificateStoreName);
    sm.CommitChanges();
}

至此,动态绑定ssl证书的功能就实现了,希望能帮到跟我一样不太熟悉ssl证书的小伙伴们。

最新补充

由于最近更换了服务器,系统由之前的windows server 2008R2升级到windows server 2016,从而发现上述动态绑定ssl证书方法出现绑定失败的异常,通过一系列的调试,最终将问题锁定在 var store = new X509Store(StoreName.AuthRoot, StoreLocation.LocalMachine) 这一句上,相比windows server 2008R2,在windows server 2016系统上导入ssl证书增加了选择证书存储这个选项,所以不能固定的使用 StoreName.AuthRoot(第三方根证书颁发机构),而是应该根据导入证书时选择的证书存储方式进行设置,分为 个人Web宿主,分别对应 MyWebHosting,如下图

证书存储
以下是调整后的方法,亲测可用

/// <summary>
/// 增加绑定域名(ssl)
/// </summary>
/// <param name="webName">站点名称</param>
/// <param name="port">端口</param>
/// <param name="bindingDomainName">绑定域名</param>
/// <param name="storeName">证书存储位置</param>
public void AddHostHeaderSSL(string webName, string port, string bindingDomainName, string storeName)
{
    string pfx = Directory.GetFiles(pfxPath, "*.pfx", SearchOption.AllDirectories).FirstOrDefault();
    ///storeName代表证书存储位置;
    ///当系统为windows server 2016以下时,storeName为 AuthRoot;
    ///当系统为windows server 2016及以上时,根据导入ssl证书时选择的证书存储方式决定,
    ///选择“个人”,storeName为 My,选择Web宿主,storeName为 WebHosting
    var store = new X509Store(storeName, StoreLocation.LocalMachine);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);

    var certificate = new X509Certificate2(pfx, certPwd, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
    store.Add(certificate);
    store.Close();
    var certificateStoreName = store.Name;
    var certificateHash = certificate.GetCertHash();

    ServerManager sm = new ServerManager();
    string bindingInformation = "*:" + port + ":" + bindingDomainName;
    sm.Sites[webName].Bindings.Add(bindingInformation, certificateHash, certificateStoreName);
    sm.CommitChanges();
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值