做Dynamics CRM本地部署运维的老哥,应该都有过半夜被证书搞醒的经历。证书这东西平时存在感很低,一旦到了快过期或者需要更换的节点,能把整个IFD登录流程弄得七零八落——用户要么连不上crm.contoso.com,要么在AD FS跳转一圈之后又弹回一个401和看不懂的错误页。今天这篇就把Dynamics CRM证书更换这条线完整捋一遍,从证书在环境里的作用范围,到替换前要准备什么,再到具体的IIS、AD FS、CRM三层更新步骤,最后把常见的坑也一并列出来。不敢说能覆盖所有版本的所有细节,但只要你的环境是“Dynamics CRM/365本地部署 + IFD + AD FS”的经典架构,照着这个思路走,证书更换基本不会翻车。
1. 证书在Dynamics CRM环境里到底扮演什么角色
1.1 一张证书牵动了哪些组件
很多第一次做证书更换的同学,以为“换证书”就是把新证书导进服务器,然后去IIS里把站点绑定点一下。这个理解放在普通网站没问题,但在Dynamics CRM的IFD架构里,证书不是一个孤立的东西,它同时挂在三四条信任链上,任何一环没跟上,登录流程就断。
先说最直观的HTTPS加密层。CRM的Front End站点、VDir站点、还有诊断相关站点,都绑在IIS的443端口上,浏览器和CRM服务器之间的大多数流量靠这份证书做TLS加密。用户访问crm.contoso.com或者SDK接口,第一步就是校验这张证书。这个没换对,用户连页面都打不开。
第二环是AD FS侧。AD FS自己也有两个层面的证书:一个是AD FS网站本身的SSL证书,也就是用户浏览器走到https://sts.contoso.com时校验的那张;另一个是令牌签名证书,AD FS用它的私钥对SAML令牌做签名,CRM用它的公钥验证这个令牌是不是真的来自受信任的AD FS。后者一旦更换,CRM那边的配置如果不跟着改,登录流程就会在“AD FS认证成功、跳转回CRM”的时候断掉。
第三环是CRM部署级别的配置。在Deployment Manager里有一块Claims-Based Settings,里面存了AD FS的联邦元数据地址、联合标识符,以及用于验证令牌的证书信息。这份配置实际上落到了MSCRM_CONFIG数据库的FederationProvider表里。所以你看,同一个“证书更换”动作,实际要改的是三四处不同位置,不是IIS一个地方能搞定的。
另外补充一句,如果你的环境里还用了Server-to-Server认证、Webhook、外部自定义服务等场景,那可能还会涉及额外的应用证书。这类证书和IFD登录链路无关,别混为一谈。咱们这篇文章先聚焦经典的IFD + AD FS登录链路。
1.2 怎么判断你的环境需不需要换证书
判断时机其实没那么玄乎,常见的信号有这么几类:
第一类是证书即将到期。证书有效期在Windows服务器上一般会有事件日志警告,通常在到期前60天或者30天开始出现。你可以打开事件查看器,翻到System和Application日志,搜Crypto、Certificate、AD FS相关的警告。还有更直接的办法,去certlm.msc里看一眼NotAfter字段。
第二类是用户已经开始报错。比如浏览器访问crm.contoso.com提示“连接不是私密连接”,或者在AD FS登录成功后跳回CRM时报401、403、证书验证失败之类的错误。这种报错未必都是证书到期,也可能是私钥权限、证书链不全、SAN不匹配导致的,但无论如何都该去查证书状态。
第三类是主动变更需求。比如公司换了根CA、内部证书要改成商业证书、SAN清单里要加新的访问域名、或者原来证书是单域名证书要升级成通配符证书。这种主动变更反倒是最好的时机,因为你可以提前规划维护窗口,而不是等化了再救火。
我个人的习惯是,不管有没有收到警告,每季度用PowerShell把CRM相关服务器的证书状态刷一遍,看一遍NotAfter和SAN列表,比什么都安心。尤其是证书链里的中间CA证书,经常被忽略,出了问题很难一眼定位。
2. 证书更换前必须做好的准备
2.1 证书申请与SAN命名清单
换证书的第一步不是去服务器上导入证书,而是先把SAN清单理清楚。证书的Subject Alternative Name(SAN)决定了它能为哪些域名做加密,少一个域名,用户访问特定地址就会报证书不匹配。
以一套经典的CRM IFD环境为例,通常要覆盖这些地址:
- CRM主入口:https://crm.contoso.com
- 如果有多个组织,可能有对应的组织入口,比如https://dev.contoso.com、https://test.contoso.com
- AD FS的入口:https://sts.contoso.com
注意,很多时候CRM和AD FS用的是同一张证书,也可能是两张不同的证书。如果你们环境里STS是个单独的域名,那就需要确认你准备申请的这张证书把sts.contoso.com也覆盖进去了,否则只改CRM侧,AD FS那一段还是会报证书错误。
申请证书之前,我建议先把现有证书的SAN列表导出来做对照:
$oldCert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq "旧证书指纹" } $oldCert.DnsNameList | ForEach-Object { $_.Unicode }拿到当前SAN清单之后,检查一下有没有需要新增的域名,确认没问题再去走证书申请流程。一定要记住:新证书的SAN清单必须完全覆盖旧证书的SAN清单,除非你确认某个域名确实已经不再使用。漏掉一个域名,你就等于给自己埋了一个后期必现的故障。
另外,如果你的证书来自内部CA,要确认证书模板支持SAN自定义,一般的Web Server模板都可以,但在证书申请请求里要正确配置。如果来自商业CA,申请时也要把SAN清单填完整,商业CA对这个字段查得很严。
2.2 备份、快照与回滚方案
证书更换这件事,最怕的不是操作不熟,而是出了问题没有回头路。所以动手之前必须做四件事。
第一件,备份IIS的配置。IIS的站点绑定信息都在applicationHost.config里,稳妥的做法是交给IIS自带的备份机制:
%windir%\system32\inetsrv\appcmd.exe add backup "PreCRM2024CertChange"这个命令会把IIS的配置快照存到系统目录下,想回滚的时候用appcmd restore backup就能恢复。
第二件,导出旧证书的PFX。就算你是“正常到期替换”,旧证书的私钥备份也建议保留一份,存到加密的U盘或者密码保险库里。万一新证书导入后立即出问题,把旧证书绑回去就能快速恢复。
第三件,记录AD FS当前状态。在AD FS服务器上跑一遍下面的命令,留个截图或者文本记录:
Get-AdfsCertificate -CertificateType "Token-Signing" | Format-List Thumbprint, IsPrimary, IsSecondary Get-AdfsCertificate -CertificateType "Token-Decryption" | Format-List Thumbprint, IsPrimary, IsSecondary Get-AdfsProperties | Select-Object AutoCertificateRollover记录的目的,是让你在最后清理阶段知道哪张证书是旧的,哪张是新的,别一不留神把新证书删了。
第四件,确认CRM部署配置里的当前值。打开Deployment Manager,进入Claims-Based Settings相关的页面,把当前显示的AD FS地址和证书指纹记录下来。有条件的话,给MSCRM_CONFIG数据库做一个备份,虽然一般用不到,但这是最保险的回滚依据。
维护窗口也要提前定。整个切换动作正常来说可以控制在半小时以内,但验证时间、回滚时间都要留出来。我建议至少预留两小时,并且通知业务方在这个时间段内不要做数据批量导入、不要跑关键报表。
3. 证书替换实操全流程
3.1 第一步:IIS站点绑定更新
先说CRM侧。把新证书导入到CRM服务器本地计算机的个人证书存储,这步在certlm.msc里做就行,路径是“本地计算机 → 个人 → 证书”,导入PFX时记得把“导出私钥”勾上。如果证书是内部CA发的,还得确认根证书和中间证书也在这个环境里,否则IIS绑定和客户端校验都会出问题。
然后确认新证书的SAN对不对:
$newCert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq "AA11BB22CC33DD44EE55FF66778899AABBCCDD" } $newCert.DnsNameList | ForEach-Object { $_.Unicode }接下来更新站点的HTTPS绑定。我用的是PowerShell批量更新,避免漏掉站点:
Import-Module WebAdministration $thumb = "AA11BB22CC33DD44EE55FF66778899AABBCCDD" $newCert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq $thumb } $sites = @("Microsoft Dynamics CRM Front End", "Microsoft Dynamics CRM VDir") foreach ($siteName in $sites) { $bindings = Get-WebBinding -Name $siteName -Protocol "https" foreach ($b in $bindings) { $b.AddSslCertificate($newCert.GetCertHash(), "My") Write-Host "$siteName 绑定的证书已更新为 $thumb" } }这里要特别强调一下:VDir站点很容易被漏掉。有些运维只改了Front End站点的绑定,结果SDK接口、Web Services地址还是旧证书,用户正常网页能开,但Outlook客户端、数据导入服务这类走接口的工具就会报证书错误。所以批量脚本一定要把VDir也带上。
改完绑定之后,检查一下所有HTTPS绑定是不是都已经指向新证书:
Get-WebBinding | Where-Object { $_.Protocol -eq "https" } | Format-Table Site, HostHeader, CertificateHash如果某个绑定还是旧指纹,单独再处理。这里我踩过的坑是:有的环境里同一个站点可能有多个HTTPS绑定,分别绑定不同主机头,如果你只改其中一个,其他绑定依然是旧证书。务必用上面的命令全量扫一遍。
3.2 第二步:AD FS证书轮换
AD FS这边涉及两类证书,先说SSL证书。AD FS网站的HTTPS绑定也要换成新证书,操作和在CRM服务器上一样,去AD FS服务器上更新对应IIS站点的443绑定。AD FS站点多数情况下是“Default Web Site”,但也可能改过名,实际以你的IIS为准:
(Get-WebBinding -Name "Default Web Site" -Protocol "https").AddSslCertificate($newCert.GetCertHash(), "My")ACE完了SSL绑定,接下来是整个证书更换里最关键的一步:令牌签名证书的轮换。AD FS允许同时存在主证书和次要证书,官方推荐的做法是先把新证书添加为次要证书,确认一切正常后再把它升为主证书,旧证书自动降为次要,最后再清理。
在AD FS服务器上执行:
# 查看当前令牌签名证书 Get-AdfsCertificate -CertificateType "Token-Signing" | Select-Object Thumbprint, IsPrimary, IsSecondary # 添加新证书为次要证书 Add-AdfsCertificate -CertificateType "Token-Signing" -Thumbprint "AA11BB22CC33DD44EE55FF66778899AABBCCDD" # 再确认状态,新证书应该是 IsSecondary=True Get-AdfsCertificate -CertificateType "Token-Signing" | Select-Object Thumbprint, IsPrimary, IsSecondary # 确认无异常后,把新证书升为主证书 Set-AdfsCertificate -CertificateType "Token-Signing" -Thumbprint "AA11BB22CC33DD44EE55FF66778899AABBCCDD" -IsPrimary $true # 重启AD FS服务让配置彻底生效 Restart-Service adfssrv升为主证书这个动作做完了,别忘了去浏览器打开AD FS的联邦元数据地址,确认元数据里公布的是新证书:
https://sts.contoso.com/FederationMetadata/2007-06/FederationMetadata.xml
打开后搜索X509Certificate或者直接看证书信息,如果元数据里还是旧证书,说明AD FS服务还没刷新完毕,等一会再刷新页面。
这里说下为什么不要直接删旧证书。SAML令牌有一定的生命周期,用户和客户端可能缓存着旧的令牌,AD FS也可能会验证旧令牌的签名。旧证书保留为次要证书一段时间,能保证过渡期内的认证请求不会因为签名证书不匹配而失败。直接一步到位删掉旧证书,很容易造成一段时间的登录抖动。
如果你的AD FS是一个多节点农场,切记要把新证书导到每一台节点的本地证书存储里,AD FS配置可以同步,但证书文件本身不会自动复制到所有节点。
3.3 第三步:更新CRM部署配置中的令牌证书
这步是很多人最容易漏的,也是导致“AD FS登录成功但跳回CRM报401”的头号原因。CRM在验证AD FS签名令牌时,用的是部署级别配置里保存的那份证书信息。AD FS那边证书换了,CRM这边还拿着旧指纹,两边对不上,验证自然失败。
操作入口在Deployment Manager。在部署节点上右键进属性,找到Claims-Based Settings相关页签,具体名字在不同版本里可能略有差异,比如Claims、身份验证、Authentication之类,但本质一样。页面里会显示当前的AD FS联合元数据地址、联合标识符、当前使用的证书指纹等信息。把证书区域切换到新证书,确认后保存。
保存之后,别急着走,在CRM服务器上重置IIS,让应用程序池把新配置加载进来。最省事的命令是:
iisreset /noforce如果不想整个IIS重启,也可以找到CRM对应的应用程序池,单独回收:
Import-Module WebAdministration Restart-WebAppPool -Name "CRMAppPool"应用程序池的真实名称每个环境不一定一样,先GET一下池列表再回收,别硬写。这个动作的目的是让CRM进程重新读取FederationProvider表里的证书信息。
有朋友会问,Deployment Manager里看不到新证书怎么办?这种情况十有八九是证书没装到当前服务器本地计算机的个人存储里,或者证书不带私钥。去certlm.msc确认一下,然后关掉重新打开Deployment Manager再看。如果还是不行,确认一下AD FS新证书到底是不是已经设为主证书,有些版本里CRM去读取证书时要求它是当前主证书。
3.4 第四步:验证与收尾
证书换完不是直接宣布结束,验证环节至少要走一遍,而且要用不同角度去验。
第一,浏览器验证。最好用无痕窗口,直接访问crm.contoso.com,看是否会跳转到sts.contoso.com,登录用户名密码之后是否能正常跳回CRM并进入应用。这一步过了,说明整条IFD链路基本通了。
第二,接口验证。如果你有Outlook客户端、数据集成工具或者任何调用CRM Web Services的程序,挑一两个重点场景测一下。重点看它们访问的是不是VDir地址,证书错误有没有消失。
第三,证书链验证。在浏览器里点开证书信息,确认系统识别到的证书链是完整的,没有“无法验证到此证书的颁发者”之类的提示。如果证书来自内部CA,客户端机器上必须安装了根证书和中间证书,这个可以通过组策略统一下发。
第四,日志验证。CRM服务器上查看事件查看器里的Microsoft Dynamics CRM日志,确认没有令牌签名相关的错误。AD FS服务器上也翻一下AD FS日志,确认没有证书相关的告警。
验证通过之后,再等一段时间再做清理。我的习惯是至少等一周,确保不会有用户拿着旧令牌访问系统。清理的时候把AD FS里次要的旧证书移除:
Remove-AdfsCertificate -CertificateType "Token-Signing" -Thumbprint "旧证书指纹"同时把本地证书存储里的旧证书删除,但PFX备份保留一段时间,至少放在安全的位置存到下次证书更换之后。
4. 常见问题与排查技巧实录
4.1 登录AD FS成功后跳回CRM却报401
这是证书更换后最多发的故障,没有之一。用户输入账号密码,AD FS都显示登录成功了,结果浏览器跳到CRM地址时冒出一个401或者“签名验证失败”。
原因基本锁定在CRM部署配置。AD FS的令牌签名证书已经换了,但CRM的Claims-Based Settings里还留着旧证书指纹,导致CRM验证不了新证书签发的令牌。解决办法就是按3.3的流程,到Deployment Manager里把证书更新掉,然后重置IIS。这里有个细节容易踩:如果你只把新证书添加为AD FS次要证书,还没升为主证书,CRM的Claims设置页里有概率认不出这张证书,所以建议先升主,再改CRM配置。
4.2 换完证书后浏览器提示证书链不完整
这个现象常见于内部CA换证或者从根CA换到企业CA的场景。浏览器打开页面,地址栏显示锁是红的或者带感叹号,点开证书详情,提示“无法将此证书验证到受信任的根证书颁发机构”。
根子在于客户端不信任签发新证书的CA。就算服务器端证书导得再对,客户端的“受信任的根证书颁发机构”和“中间证书颁发机构”存储里没有对应CA证书,信任链就建立不起来。解决办法是把根CA证书和中间CA证书通过组策略或MDM下发到所有客户端。在服务器端,也要确认本地机器上已经完整安装了证书链,否则IIS在TLS握手时就不会把中间证书返回给客户端。
4.3 主站点了新证书,但部分接口地址仍然报证书错误
这个就是我在3.1里反复强调的“VDir遗忘症”。主站点看着一切正常,网页能开,但SDK、Web Services、Outlook客户端这类走接口的路径还是旧证书。
排查方法特别简单,全量遍历所有HTTPS绑定,按证书哈希筛选:
Get-WebBinding | Where-Object { $_.Protocol -eq "https" } | Select-Object Site, HostHeader, sslFlags, CertificateHash把输出里的证书哈希和旧证书指纹比对,只要有HTTPS绑定还是旧指纹,就继续替换。多组织环境尤其要注意,每个组织可能有独立的Front End入口,它们的绑定不一定都挂在同一个站点下。
4.4 签发证书时间与客户端时间不一致之类的小问题
这类问题相对少见,但也值得提一下。如果客户端机器时间偏差过大,即使证书本身没问题,浏览器也会因为“证书尚未生效”或“证书已过期”报错。排查时看一眼客户端时间,再跟服务器时间同步一下就行。另外,别忽略文本框里的主机名——你访问crm.contoso.com,证书里的SAN必须包含crm.contoso.com,这个不匹配也是高频报错点。
| 现象 | 大概率原因 | 解决方向 |
|---|---|---|
| 网页提示证书过期/不受信任 | IIS绑定未全部更新、证书链缺失 | 全量更新HTTPS绑定,下发CA证书 |
| AD FS页面提示证书错误 | STS站点IIS绑定未更新或SAN缺域名 | 更新AD FS服务器上的IIS绑定 |
| 登录成功但跳回CRM报401 | CRM部署配置仍用旧令牌证书 | 更新Claims-Based Settings |
| Outlook或SDK接口报证书错误 | VDir站点绑定漏改 | 按证书哈希全量扫描绑定 |
| AD FS控制台看不到新证书 | 证书未导入本地个人存储或缺少私钥 | 重新导入PFX并确认可导出私钥 |
我个人在实际操作中还有个小习惯:证书更换完成后,把新证书的指纹、SAN清单、过期时间、换证日期记到运维文档里,顺便在AD FS和CRM两侧各留一份当时的PowerShell输出。下次再做同样操作,翻一下记录就能快速确认环境里哪些位置还挂旧证书。证书这事儿,最怕的不是过程繁琐,而是你以为全换完了,结果某个角落漏了一个绑定,半夜又得爬起来收尾。