Windows 证书存储实务指南——应该放入用户存储还是计算机存储

· 更新日期: · · 证书, Windows, 安全, PKI, TLS, PowerShell, 业务应用, 信息系统

更新记录(仅首版,2026年08月01日 发布)
首次发布
引用本文(DOI(已登记存档): 10.5281/zenodo.22175588)

以下 DOI 指向先前登记的存档,内容可能与当前正文不同。引用当前正文时,请使用本页网址。

Go Komura(2026)。《Windows 证书存储实务指南——应该放入用户存储还是计算机存储》。小村软件有限公司。 https://comcomponent.com/zh-CN/blog/windows-certificate-store-guide/

DOI(已登记存档)
10.5281/zenodo.22175588
DOI(上次登记版本)
10.5281/zenodo.22175589

“在线资格确认的终端更换时,把客户端证书重新导入新电脑后就连不上了。”“开发机上能连通银行 API,改成 Windows 服务后却提示‘找不到证书’。”“说到底,certmgr.msc 里看到的证书和 certlm.msc 里看到的证书,哪个才是真的都分不清。”——承接带客户端证书的 Web API 联动开发时,这类咨询会定期找上门。

医疗机构的在线资格确认、电子申请、银行系 API、与合作方之间的 EDI。过去只有大企业基础设施人员才接触的客户端证书,如今中小企业的信息系统负责人和业务应用开发者也要经手。而证书相关的故障,其实只集中在寥寥几种模式上。放错位置、忘记授予私钥权限、忘记有效期——就是这三种。

本文面向使用客户端证书的业务应用开发者,以及被指派做证书更换工作的信息系统负责人,以“放入用户存储还是计算机存储”这一判断为主线,从 Windows 证书存储的结构,到私钥的权限授予、用 PowerShell 盘点有效期,再到从 .NET 使用证书的代码,一次性梳理清楚。内容基于 2026 年 8 月时点 Microsoft Learn 的一手资料。

1. 先说结论

  • Windows 的证书存储分为“用户(CurrentUser)”和“计算机(LocalMachine)”两个体系。用户存储按账户各自独立(位于注册表 HKEY_CURRENT_USER 下),计算机存储则整台电脑共用(位于 HKEY_LOCAL_MACHINE 下)。12
  • 管理工具也有两个。certmgr.msc 打开当前用户的存储,certlm.msc 打开本地计算机的存储。在 PowerShell 中则是 Cert:\CurrentUserCert:\LocalMachine34
  • 放进哪一个,由“使用该证书的程序以谁的身份运行”决定。面向交互式用户的应用放用户存储,Windows 服务、IIS、任务计划程序的无人值守运行原则上放计算机存储(第 3 章的判断表)。
  • “开发阶段能用,做成服务就找不到”的原因几乎只有一个。开发者放进自己用户存储的证书,以其他账户运行的服务打开 CurrentUser 是看不到的(第 3 章)。
  • 证书和私钥是两回事。仅仅放入计算机存储,服务账户通常读不到私钥。要在 certlm.msc 的“管理私钥”里为运行账户授予读取权限。5
  • 导入 pfx 时,私钥默认变为不可导出。Import-PfxCertificate 只要不指定 -Exportable,就会以私钥无法再次导出的形式导入。这不是缺陷,而是理想的默认值。6
  • 过期靠盘点自动化来防。Get-ChildItem Cert:\LocalMachine\My -ExpiringInDays 60 这样,可以机械地筛出在指定天数内到期的证书。4
  • 把指纹(拇印)硬编码进代码或配置,每次更新证书都会出问题。因为新证书的指纹必定会变。把指纹外置到配置中,再加上新旧并行期间,这是设计的基本原则(第 5 章、第 7 章)。

图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 41 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle

2. 证书存储的全貌——两个位置与逻辑存储

2.1. 用户与计算机两个体系

Windows 的证书存储大致分为两个“位置”。1

  • 计算机(本地计算机,LocalMachine)的证书存储:每台电脑只有一份,为该电脑上的所有用户和服务共用。其实体位于注册表 HKEY_LOCAL_MACHINE\Software\Microsoft\SystemCertificates 下。2
  • 用户(当前用户,CurrentUser)的证书存储按用户账户各自独立。其实体位于 HKEY_CURRENT_USER\Software\Microsoft\SystemCertificates 下,也就是用户配置文件的一部分。2

除此之外还有按服务账户划分的存储3,其实体是按服务名区分的注册表项。2 实务中首先要掌握的是前面这两个。

有一条重要的规格需要记住。用户存储下的各逻辑存储,除“个人”以外,都会继承并显示计算机存储中同名存储的内容1 例如把内部 CA 的证书放进计算机存储的“受信任的根证书颁发机构”,那么所有用户的“受信任的根证书颁发机构”里也会出现这张证书。反过来说,唯有“个人”存储不会被继承,所以客户端证书(也就是放进个人存储的东西)必须自己决定“需要让谁看到”。这种不对称性,正是本文通篇的主角。

用户(CurrentUser)按账户各自独立计算机(LocalMachine)每台电脑一份、所有用户和服务共用继承内容并显示继承继承个人(My)※不会被继承,放在哪里要自己决定受信任的根证书颁发机构(Root)中间证书颁发机构(CA)受信任的发布者(TrustedPublisher)个人(My)受信任的根证书颁发机构(Root)中间证书颁发机构(CA)受信任的发布者(TrustedPublisher)

2.2. 主要的逻辑存储

每个位置的内部又按角色划分为不同的逻辑存储。在 certmgr.msc / certlm.msc 中看到的文件夹就是它们,从 PowerShell 或命令行查看时使用英文内部名。24

显示名 内部名 用来放什么
个人 My 自己(这台电脑、这个用户)使用的证书。客户端证书、服务器证书都在这里,与私钥关联的也是这里
受信任的根证书颁发机构 Root 作为信任起点的根 CA 证书。放进这里的 CA,其下级都会被“信任”
中间证书颁发机构 CA 连接根与末端的中间 CA 证书,是构建证书链的材料
受信任的发布者 TrustedPublisher 作为已签名软件的发布者而信任的证书(第 8 章)

2.3. 三个观察窗口——certmgr.msc / certlm.msc / Cert: 驱动器

查看同一个存储的手段有三种。34

  • certmgr.msc:打开当前用户存储的管理控制台。
  • certlm.msc:打开本地计算机存储的管理控制台。
  • PowerShell 的 Cert: 驱动器:可以在 Cert:\CurrentUser\...Cert:\LocalMachine\... 的层级下像操作文件系统一样操作存储。证书按指纹识别。

另外,向 mmc.exe 手动添加证书管理单元时,要从“用户账户”“计算机账户”“服务账户”三种类型中选择目标。非管理员用户只能管理自己用户账户的存储。3

排查故障的第一步,是让“应用在看哪个存储”和“自己在看哪个存储”对上。一边盯着 certmgr.msc 一边排查服务的故障,因为看的地方不同,永远也得不出答案。

3. 放进哪一个——按程序的运行形态决定的判断表

判断标准只有一条。使用该证书的程序,以谁的账户运行。

运行形态 运行账户 放入的存储 备注
交互式用户启动的桌面应用 登录用户本人 用户(Cert:\CurrentUser\My) 需要按使用者的账户逐个导入。共享电脑由多人使用时,也可以考虑计算机存储
Windows 服务 LocalSystem / NETWORK SERVICE / 专用服务账户 计算机(Cert:\LocalMachine\My) LocalSystem 以外(NETWORK SERVICE、专用账户等)必须授予私钥的读取权限(第 4 章)。LocalSystem 凭默认的 SYSTEM 权限即可读取
IIS 上的 Web 应用 应用程序池的标识 计算机 同上
任务计划程序的无人值守运行(不论用户是否登录都执行) 任务中指定的账户 建议计算机 用运行账户的用户存储也能跑起来,但只会增加用户配置文件和存储可见性的验证工作,好处不多
浏览器中的电子申请、Web 身份验证 登录用户本人 用户 从“不让分发对象本人以外的人使用”这层意义看也很自然

拿不准时,无人值守运行的放计算机存储,人来操作的放用户存储

3.1. 典型故障剖析——“开发阶段能用,做成服务就找不到”

这类故障可以按下面的步骤精确复现。

  1. 开发者在自己的电脑上双击 pfx 导入。向导的默认值是“当前用户”,于是证书进了开发者账户的用户存储
  2. 开发中的应用从 Visual Studio 启动,也就是以开发者账户运行,所以打开 StoreLocation.CurrentUser 就能找到证书。能用。
  3. 在生产服务器上注册为 Windows 服务。服务以 NETWORK SERVICE 或专用账户运行。
  4. 服务代码打开的 CurrentUser,是服务运行账户的用户存储。那里是空的。“找不到证书”。
生产服务器开发机部署同一个程序代码打开的 CurrentUser 是服务账户的用户存储注册为 Windows 服务运行账户是 NETWORK SERVICE 等那里是空的→“找不到证书”进入开发者账户的用户存储双击 pfx 导入向导的默认值是“当前用户”从 Visual Studio 运行也就是以开发者账户运行打开 CurrentUser 就能找到→ 能用

关键在于,用户存储“有多少账户就有多少份”。即使管理员打开 certmgr.msc 确认“不是已经放进去了吗”,那也只是管理员自己的存储,而不是服务账户的存储。正确的处理不是临时复制一份了事,而是重新放进计算机存储,并把代码也统一到 StoreLocation.LocalMachine。而且要连下一章的权限授予一起做,才算一套完整操作。

4. 私钥与访问权限——第二种典型故障

4.1. 证书和私钥是两回事

证书存储列表里看到的是证书(公开信息),而不是私钥本身。客户端身份验证实际需要的是用私钥完成的签名处理,所以“在列表里看得到”和“能用”是两个不同的问题。混淆这一点,就会遇到“证书明明在,TLS 握手却失败”“出现 Access Denied 一类的内部错误”这种表面上很难理解的故障。

4.2. pfx 导入的实务——是否可导出是一项决策

证书与私钥的配对通过 pfx(PKCS #12)文件交付,可以用 Import-PfxCertificate 导入存储。6

$pwd = Get-Credential -UserName '(请在下方输入密码)' -Message 'PFX 的密码'
Import-PfxCertificate -FilePath C:\certs\client.pfx `
    -CertStoreLocation Cert:\LocalMachine\My -Password $pwd.Password

这里重要的是这样一个默认行为:只要不加 -Exportable,导入的私钥就无法再次导出6 出于“以后方便迁移”的想法而一律以可导出的方式导入,等于给私钥多开一条外流通道。把原始 pfx 安全保管,存储中的私钥以不可导出为基本——这是本公司的推荐。另外,原始 pfx 及其密码的保管,恰恰最容易被以明文形式放着不管。相关思路整理在“Windows 应用的敏感信息存储——用 DPAPI 摆脱明文配置”和“PowerShell 中凭据的安全处理方式”里。

4.3. 为服务账户授予私钥权限

放进计算机存储的证书,其私钥默认通常只有管理员和 SYSTEM 才能读取。因此,以 LocalSystem 运行的服务保持默认就能读到私钥,但如果以 NETWORK SERVICE、专用服务账户、IIS 应用程序池标识等其他账户运行,就要给运行账户明确授予读取权限。操作可以在证书管理单元的界面中完成。5

  1. 打开 certlm.msc(或以计算机账户为目标的证书管理单元)。
  2. 在“个人”→“证书”中右键点击目标证书,从“所有任务”打开“管理私钥”
  3. 在“安全”选项卡中添加运行账户(NETWORK SERVICE、专用服务账户、IIS 的应用程序池标识等),并允许“读取”5

完全控制不需要。只用于签名的话,读取就够了。反过来,因为跑不起来就给 Everyone 完全控制,等于把私钥降格到和明文密码同等的待遇,请务必避免。放入计算机存储和授予私钥权限,永远是配套的一套操作——只要把这一点写进操作手册,这一类故障就会消失。

5. 防止过期故障——盘点、更换、台账

5.1. 用 PowerShell 盘点

证书的有效期存放在 NotAfter 属性中。对 Cert: 驱动器执行 Get-ChildItem,就能机械地盘点。4

# 按有效期顺序列出计算机存储的“个人”
Get-ChildItem Cert:\LocalMachine\My |
    Sort-Object NotAfter |
    Format-Table Thumbprint, Subject, NotAfter

# 只提取 60 天内到期的(指定 0 则为已过期)
Get-ChildItem -Path Cert:\LocalMachine\My -ExpiringInDays 60

-ExpiringInDays 是返回“在指定天数内到期的证书”的参数,为 0 时输出已经过期的证书。4 把它做成按月执行的计划任务,遍历所有服务器,再把结果汇总到邮件或台账里——仅此一项,“因过期而周一早上资格确认通不过”这类故障基本就能防住。

5.2. 更换的步骤——新旧并行期间与指纹的陷阱

证书更新不是“删掉再放进去”,而是“先添加再切换,确认之后再删除”。

  1. 把新证书(pfx)导入同一个存储。指纹不同,所以新旧证书可以在同一个存储中共存。
  2. 为新证书授予私钥权限(第 4 章)。更新时最容易忘的就是这里。权限是按证书的私钥分别附加的,所以换了证书就要重新授予一次。
  3. 向对方系统的申报(针对需要证书事前登记的 API),要在继续用旧证书运行的状态下先办完,确保有一段新旧证书都能被接受的并行期间。先切换的话,对方会拒绝新证书,导致生产环境的通信中断。
  4. 把应用的配置切换到新证书,并验证运行情况。
  5. 经过足够长的一段时间后,删除旧证书。
1. 把新 pfx 导入同一个存储(新旧共存)2. 为新证书授予私钥权限3. 向对方事前登记(继续用旧证书运行)4. 改写配置中的指纹并切换、验证运行5. 并行期间过后删除旧证书

这时最大的陷阱,是写在配置文件或代码里的指纹。指纹对每张证书是唯一的,更新后必定会变。只要有一处还引用着旧指纹,就会出现“证书明明更新了却连不上”。用台账管理指纹写在哪些地方(应用配置、IIS 绑定、脚本、对对方的申报),才最可靠。

5.3. 建议建立证书台账

说是台账,一开始一张 Excel 表就够了。至少要建立用途 / 颁发者 / 使用者主体 / 指纹 / 所在位置(服务器名 + 存储)/ 拥有私钥权限的账户 / 有效期 / 更新步骤的链接 / 负责人这些列,并与 5.1 的盘点结果核对。证书故障的实质不是技术问题,而是“没有人手里有一份完整清单”的问题,所以台账最见效。

6. 验证与解读失败——证书链与根证书分发

6.1. 证书链验证的基础与 certutil

“此证书不受信任”一类的错误,是从末端证书到根 CA 的证书链(信任路径)在某处断开的状态。排查时 certutil 很好用。7

取不到(提示、AIA、存储都取不到)没有被分发已过期末端证书(客户端证书、服务器证书)中间 CA 证书放在中间证书颁发机构(CA)存储根 CA 证书放在受信任的根证书颁发机构(Root)无法构建证书链(典型原因 1)“不受信任”错误(典型原因 2)有效期错误(典型原因 3)
:: 构建并验证证书文件的证书链(附带获取吊销检查用的 URL)
certutil -urlfetch -verify client.cer

:: 如果目标应用使用用户存储,加上 -user 在相同上下文中验证
certutil -user -urlfetch -verify client.cer

:: 转储存储的内容(加上 -user 则为用户存储)
certutil -store My
certutil -user -store My

certutil -verify 会验证证书、CRL 和证书链,不指定 CACertFile 时会构建完整的证书链并加以验证。7 输出很长,但能从中读出信任在哪一层断掉、吊销信息是否取到。典型原因有三个:(1)取不到中间 CA 证书(TLS 对端没有发送,从证书的 AIA 信息也取不到,“中间证书颁发机构”存储里也没有);(2)内部 CA 的根证书没有分发到“受信任的根证书颁发机构”;(3)证书本身过期。中间 CA 也可以通过对端提示或经 AIA 自动获取来解决,所以请把放进存储理解为“确保成功的手段之一”。

6.2. 内部 CA、自签名证书的根证书分发交给 GPO/Intune

使用内部 CA 或验证用自签名证书时,需要把其根证书分发到每台电脑。不要一台一台手工导入,而要纳入分发机制。

  • Active Directory 环境(GPO):把证书导入组策略 计算机配置\策略\Windows 设置\安全设置\公钥策略 下的“受信任的根证书颁发机构”,就会分发到目标电脑。8
  • Intune 管理的环境:用“受信任的证书”配置文件分发根 / 中间 CA 证书。在 Windows 上可以选择分发目标存储(计算机的根 / 中间、用户的中间)。9

如 2.1 所述,放进计算机存储的根证书会被所有用户信任。1 也正因如此,请同时正视反面的风险。把自签名证书放进“受信任的根证书颁发机构”,等于在那台电脑上种下一个新的信任起点。一旦它的私钥泄露,就会成为签发冒充任意网站或软件的证书的立足点。若要长期使用,正道是搭建妥善保护私钥的内部 CA,或者转向公共 CA 颁发的证书;自签名根证书的原则是“仅限验证环境、并设定有效期”。

7. 开发者视角——从 .NET 正确使用存储

7.1. 用 X509Store 按指纹检索

从 .NET 用 X509Store 打开存储,用 Find 取得证书。1011

using System.Security.Cryptography.X509Certificates;

static X509Certificate2 GetClientCertificate(string thumbprint)
{
    using var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

    var found = store.Certificates.Find(
        X509FindType.FindByThumbprint, thumbprint, validOnly: true);

    if (found.Count == 0)
        throw new InvalidOperationException(
            $"找不到证书: 指纹={thumbprint}, " +
            $"位置={store.Location}\\{store.Name}");

    var cert = found[0];
    if (!cert.HasPrivateKey)
        throw new InvalidOperationException(
            $"证书存在,但没有关联私钥(例如从 .cer" +
            $"导入): 指纹={thumbprint}, 位置={store.Location}\\{store.Name}");

    return cert;
}

第 3 章的判断在这里直接体现出来。服务中运行的代码用 StoreLocation.LocalMachine,交互式应用用 StoreLocation.CurrentUser。还有一点,请注意 Find 的第三个参数 validOnlytrue 只返回通过验证的有效证书11 它可以作为不会抓到过期证书的保险,但另一方面,证书链不受信任的测试用自签名证书也会落到“找不到”那一侧,所以遇到“明明放进去了却找不到”时,也要怀疑这里。另外,找不到时的错误消息里,一定要像上面的例子那样写明查找了哪个存储。第 3 章那类故障的排查时间会相差一个数量级。

7.2. 把客户端证书装到 HttpClient 上

取得的证书添加到 HttpClientHandler.ClientCertificates,就会提示给服务器。这个集合就是在基于证书的客户端身份验证中提示给服务器的证书集合。12

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(GetClientCertificate(thumbprint));

var client = new HttpClient(handler);
// 之后按普通的 HttpClient 使用

另外,在 .NET Core 系列中,文档明确写到:证书带有密钥用法(Key Usage)属性时,如果其中不包含“Digital Signature”,该证书就不会被用于发送请求。12 如果你处在委托签发客户端证书的一方,请正确传达用途(客户端身份验证)。另外,HttpClient 的创建模式一旦用错,就会引发套接字耗尽和 DNS 变更跟不上的问题。把处理程序整体设计成长生命周期的做法,正如“不要用 using 包裹 HttpClient”中所讨论的。

7.3. 硬编码的指纹在更换证书时会出问题

按指纹检索很可靠,但把指纹嵌进代码,就会每次更新证书都需要重新构建和发布。设计层面的应对分三个阶段。

  • 最低限度:把指纹外置到配置文件(appsettings 等),做到不发布也能替换。配置的位置记入 5.3 的台账。
  • 再进一步:按使用者主体名或颁发者检索,并结合 validOnly: true,从“该名称下当前有效的证书”中选出 NotAfter 最靠后的那一张。这样在新旧并行期间会自动换到新证书。不过存在抓到同名的意外证书的风险,所以要把颁发者校验和日志输出配成一套。另外,这种自动切换只有在对方不需要证书事前登记时才成立。对于需要事前登记的 API(5.2),可能会擅自切到只是导入、尚未登记的证书而导致通信中断,因此请止步于确认登记完成后再切换的配置外置方式。
  • 用运维收口:无论采用哪种方式,都要在启动时把“选了哪张证书(指纹、有效期)”记入日志。无论是故障排查还是与台账核对,这一行都很管用。

8. 与代码签名证书的关系——“受信任的发布者”存储

到这里讨论的都是用于通信(TLS)的证书,但证书存储里还并存着另一个世界——代码签名。2.2 的表中出现的“受信任的发布者(TrustedPublisher)”存储就是两者的接点,是把已签名软件的发布者证书登记为已信任的地方。它在用户和计算机两个位置都存在10,常用于通过 GPO 把内部分发应用的发布者配置到各台电脑的 TrustedPublisher 这类做法。

作为应用的“分发方”,如果需要处理代码签名或 SmartScreen 警告(“Windows 已保护你的电脑”),可以参考另一篇文章“Windows 上出现‘Windows 已保护你的电脑’的原因”。本文的知识(存储的两个体系、根证书分发)可以直接作为其前提知识使用。

9. 总结

  • 证书存储分为用户(CurrentUser)和计算机(LocalMachine)两个体系。certmgr.msc / certlm.msc / Cert: 驱动器是看同一样东西的三个窗口。排查的第一步是统一“在说哪个存储”。
  • 放的位置由“程序以谁的身份运行”决定。无人值守运行(服务、IIS、任务)原则上放计算机存储,交互式应用放用户存储。
  • “开发阶段能用,生产环境找不到”的原因,是开发者的用户存储和服务账户的用户存储是两个不同的东西。统一到计算机存储加 StoreLocation.LocalMachine 即可解决。
  • 放入计算机存储和在“管理私钥”中授予读取权限是配套的一套操作。更新时别忘了重新授予。
  • pfx 导入默认不可导出。-Exportable 只在真正需要时才用。原始 pfx 和密码的保管也要纳入设计。
  • 过期靠 Get-ChildItem Cert: ... -ExpiringInDays 的定期盘点和证书台账来防。更换按“添加→切换→确认→删除”的顺序,注意配置中的指纹是否有遗漏未更新。
  • 证书链的排查用 certutil -urlfetch -verify。内部 CA 的根证书用 GPO/Intune 分发,把自签名证书放进根存储的做法要仅限验证环境并设定有效期。
  • 代码里把指纹外置到配置,并把选中的证书记入日志。仅这一点,证书引发的故障处理就会大不一样。

相关文章

相关咨询领域

合同会社小村软件承接嵌入客户端证书的 Web API 联动(银行系 API、在线资格确认等)的业务应用开发、“找不到证书”“更新后连不上”这类故障的排查,以及证书更换步骤的整理完善。哪怕只是“不知道该看存储的哪个位置”这个阶段的咨询,也欢迎联系我们。

参考链接

  1. Microsoft Learn, Local Machine and Current User Certificate Stores. 关于计算机的证书存储对该电脑而言是本地的、为所有用户共用并位于 HKEY_LOCAL_MACHINE 下,用户的证书存储按用户账户各自独立并位于 HKEY_CURRENT_USER 下,以及用户存储除“个人”存储外会继承计算机存储的内容(在计算机的“受信任的根证书颁发机构”中添加的证书也会出现在各用户的同一存储中)的说明。  2 3 4

  2. Microsoft Learn, System Store Locations. 关于 CERT_SYSTEM_STORE_CURRENT_USER 与 CERT_SYSTEM_STORE_LOCAL_MACHINE 的注册表位置(分别位于 HKEY_CURRENT_USER 与 HKEY_LOCAL_MACHINE 的 Software\Microsoft\SystemCertificates 下)、预定义的逻辑存储为 MY、Root、Trust、CA,服务用存储位于按服务名区分的注册表项(Software\Microsoft\Cryptography\Services\ServiceName\SystemCertificates),以及另外存在用于组策略分发的存储的说明。  2 3 4 5

  3. Microsoft Learn, How to: View certificates with the MMC snap-in. 关于 certlm.msc 是管理本地设备(本地计算机)证书的工具、certmgr.msc 是管理当前用户证书的工具,证书管理单元的目标分为“计算机账户”“用户账户”“服务账户”三种,以及非管理员用户只能管理自己用户账户的证书的说明。  2 3 4

  4. Microsoft Learn, about_Certificate_Provider. 关于 PowerShell 的 Cert: 驱动器是拥有 CurrentUser 与 LocalMachine 两个存储位置的层级命名空间、可用 Get-ChildItem 列举存储与证书、-ExpiringInDays 参数返回在指定天数内到期的证书(为 0 则是已过期的证书)、-CodeSigningCert 等动态参数、NotAfter 属性中存放有效期,以及证书按指纹识别的说明。  2 3 4 5 6

  5. Microsoft Learn, How to Modify Private Key Permissions to Support Management Server or Streaming Server. 关于在以本地计算机证书存储为目标的证书管理单元中打开“管理私钥”(Manage Private Keys),并在“安全”选项卡为服务的运行账户(例如 Network Service)添加“读取”访问权限的步骤说明。  2 3

  6. Microsoft Learn, Import-PfxCertificate. 关于 Import-PfxCertificate 会把 PFX 文件中的证书与私钥导入指定存储、不指定 -Exportable 开关时导入的私钥无法导出,以及 -CertStoreLocation、-Password、-FilePath 各参数的语法与使用示例的说明。  2 3

  7. Microsoft Learn, certutil. 关于 certutil -verify 会验证证书、CRL 与证书链,不指定 CA 证书文件时会构建完整的证书链并加以验证,可以使用 -urlfetch 选项,以及 certutil -store 会转储证书存储、加上 -user 选项可以访问用户存储而非计算机存储的说明。  2

  8. Microsoft Learn, Distribute Certificates to Client Computers by Using Group Policy. 关于把证书导入组策略“计算机配置\策略\Windows 设置\安全设置\公钥策略”下的“受信任的根证书颁发机构”,从而分发到域内客户端计算机的步骤,以及所需权限(相当于 Domain Admins / Enterprise Admins)的说明。 

  9. Microsoft Learn, Create trusted certificate profiles in Microsoft Intune. 关于 Intune 的“受信任的证书”配置文件是把根或中间 CA 证书分发到受管设备的机制、作为 SCEP/PKCS 证书配置文件的前提用于建立对根 CA 的信任,以及在 Windows 上可以把分发目标存储选为“计算机证书存储 - 根”“计算机证书存储 - 中间”“用户证书存储 - 中间”的说明。 

  10. Microsoft Learn, X509Store Class. 关于 X509Store 可以指定 StoreName 与 StoreLocation(CurrentUser / LocalMachine)来构造、可以用 Open 方法和 OpenFlags(ReadOnly、OpenExistingOnly 等)打开存储、可以用 Certificates 属性取得证书集合,标准存储名包含 My、Root、CA、TrustedPublisher 等,以及 TrustedPublisher 存储在 CurrentUser 与 LocalMachine 两处都存在的说明。  2

  11. Microsoft Learn, X509Certificate2Collection.Find(X509FindType, Object, Boolean) Method. 关于 Find 方法用 X509FindType(如 FindByThumbprint)和检索值查找证书,以及第三个参数 validOnly 指定为 true 时只返回通过验证的有效证书的说明。  2

  12. Microsoft Learn, HttpClientHandler.ClientCertificates Property. 关于 ClientCertificates 属性是在基于证书的客户端身份验证中提示给服务器的 X509CertificateCollection,以及在 .NET Core 中证书存在密钥用法属性时必须包含“Digital Signature”的说明。  2

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

常见问题

汇总了咨询这一主题时常见的问题。

certmgr.msc 和 certlm.msc 有什么区别?
两者面向的存储不同。certmgr.msc 打开的是登录用户的证书存储(当前用户,CurrentUser),certlm.msc 打开的是计算机的证书存储(本地计算机,LocalMachine)。计算机存储为这台电脑上的所有用户和服务共用,管理它需要管理员权限。非管理员用户只能管理自己的用户存储。两者内部都划分为“个人”“受信任的根证书颁发机构”等逻辑存储,从 PowerShell 看,Cert:\CurrentUser 与 Cert:\LocalMachine 呈现的是相同的结构。
客户端证书应该放入用户存储还是计算机存储?
由使用该证书的程序“以谁的身份”运行来决定。交互式用户启动的桌面应用,基本放入使用者本人的用户存储(Cert:\CurrentUser\My)。通过 Windows 服务、IIS 应用程序池、任务计划程序无人值守运行的程序,则放入计算机存储(Cert:\LocalMachine\My),并为运行账户授予私钥的读取权限。用户存储按账户各自独立,开发者放进自己用户存储的证书,以其他账户运行的服务看不到。这正是“开发阶段能用,生产环境却找不到”这类故障的典型原因。
Windows 服务找不到证书或用不了证书时该确认什么?
确认分两个阶段。第一是“在看哪个存储”。如果代码打开的是 StoreLocation.CurrentUser,那就是服务运行账户的用户存储,与管理员在 certmgr.msc 中看到的自己的存储是两回事。应把证书移到计算机存储,代码也改成 StoreLocation.LocalMachine。第二是“私钥能不能读”。在列表里看得到证书与能使用私钥是两件事,计算机存储中的私钥通常默认只有管理员和 SYSTEM 能访问。请在 certlm.msc 中对目标证书打开“管理私钥”,为服务的运行账户(如 NETWORK SERVICE)授予“读取”权限。
如何用 PowerShell 提前发现证书过期?
对 Cert: 驱动器执行 Get-ChildItem 就能盘点。例如 Get-ChildItem Cert:\LocalMachine\My | Sort-Object NotAfter | Format-Table Thumbprint, Subject, NotAfter,可以按有效期顺序列出计算机存储的个人存储。再用 -ExpiringInDays 参数,还能只提取“在指定天数内到期的证书”,指定 0 则会列出已经过期的证书。把它做成按月对所有服务器执行、并把结果与证书台账核对的流程,“因过期而一早就连不上”这类故障基本就能防住。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表