我们有一个saas平台 部分在azure的cloud service 使用lets encrypt来申请证书。每一个商家申请域名之后就需要通过Lets encrypt来得到证书并绑定证书。
IIS里面能用到的证书是 放在localMachine的 WebHosting 或者 My下面 运行MMC 添加证书管理可以看到这个东西.
绑定证书的方法是可以放在webRole的OnStart 方法里面。 并使用ServerManager类 .(Microsoft.Web.Administration.dll)
大概代码是
var serverManager = new ServerManager(); var site = serverManager.Sites[0]; var bindings = site.Bindings.ToList(); foreach (var item in canBindCertificates) { var httpsBinding = bindings.FirstOrDefault(it => it.Protocol == "https" && it.Host == item.FriendlyName); if (httpsBinding != null) { httpsBinding.CertificateStoreName = _store.Name; httpsBinding.CertificateHash = item.GetCertHash(); } else { var binding = site.Bindings.Add($"*:443:{item.FriendlyName}", item.GetCertHash(), _store.Name); binding.Protocol = "https"; binding.SetAttributeValue("sslFlags", 1); //Important property } } serverManager.CommitChanges();
里面比较大的一个坑是 原来的证书会影响到这个绑定。 会导致你新绑定的域名 取不到正确的让书,或者原来的绑定失效。
需要处理的是在 ServiceDefinition.csdef文件里面加入两个没用的绑定。并在在 Webrole 启动的时候删掉哪个HostHeader为空的绑定。 其它的需要绑定都扔到动态绑定哪边。这样重新部署和新加新的网站就都正常了。
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
<Binding name="HttpsEndpointEmpty" endpointName="HttpsEndpoint1" hostHeader="" />
<Binding name="HttpsEndpoint1" endpointName="HttpsEndpoint1" hostHeader="placeholder.{xxx}.com" /> //{xxx}是你自己的域名
</Bindings>
</Site>
主要原因是配置文件没有办法设置SNI, 我们在代码里面强制把它设成SNI也会出错。(IIS打开的时候会看到SNI是没有勾选的) 。
我们是使用 AcmeClient (类库 https://github.com/ebekker/ACMESharp 示例项目 https://github.com/Lone-Coder/letsencrypt-win-simple/) 来申请证书的。发现这个东西也有一个小坑。每次申请一个新证书的进候是需要重新实例化这个类的。不然的话,在申请2个以上证书的时候会就会出错了 urn:acme:error:badNonce