「線上資格確認的端末更新作業中,把用戶端憑證重新裝進新 PC 後就連不上了」「開發機上明明連得上銀行 API,一改成 Windows 服務就說『找不到憑證』」「說到底,certmgr.msc 上看到的憑證和 certlm.msc 上看到的憑證,到底哪個才是真的都搞不清楚」──在受託開發搭配用戶端憑證的 Web API 串接時,這類諮詢會定期出現。
醫療機構的線上資格確認、電子申請、銀行系 API、與往來廠商的 EDI。過去只有大型企業的基礎架構人員才會碰的用戶端憑證,如今已經是中小企業資訊系統人員與業務應用程式開發人員都要處理的東西。而憑證相關的事故,其實可以歸納成寥寥幾種模式。放錯位置、忘記授予私密金鑰權限、忘記到期日──就是這三種。
本文以使用用戶端憑證的業務應用程式開發人員,以及負責更換憑證作業的資訊系統人員為對象,以「該放進使用者存放區還是電腦存放區」這個判斷為主軸,一口氣整理 Windows 憑證存放區的結構、私密金鑰的權限授予、用 PowerShell 進行到期日盤點,一直到 .NET 端的使用程式碼。內容以 2026 年 8 月時點 可查閱到的 Microsoft Learn 官方資訊為前提。
1. 先講結論
- Windows 的憑證存放區分成「使用者(CurrentUser)」與「電腦(LocalMachine)」兩大體系。使用者存放區依帳戶各自獨立(位於登錄檔的 HKEY_CURRENT_USER 之下),電腦存放區則是整台 PC 共用(位於 HKEY_LOCAL_MACHINE 之下)。12
- 管理工具也有兩個。certmgr.msc 開啟目前使用者的存放區,certlm.msc 開啟本機電腦的存放區。從 PowerShell 來看,分別對應
Cert:\CurrentUser與Cert:\LocalMachine。34 - 要放進哪個存放區,取決於「使用這張憑證的程式是以誰的身分執行」。互動使用者的應用程式放使用者存放區,Windows 服務、IIS、工作排程器等無人值守執行的情況,原則上放電腦存放區(見第 3 章的判斷表)。
- 「開發時期能動、改成服務後卻找不到」的原因幾乎只有一個。開發人員放進自己使用者存放區的憑證,以另一個帳戶執行的服務從其 CurrentUser 是看不到的(第 3 章)。
- 憑證和私密金鑰是不同的東西。光是放進電腦存放區,服務帳戶通常還是讀不到私密金鑰。要用 certlm.msc 的「管理私密金鑰」,授予執行帳戶讀取權限。5
- 匯入 pfx 時,私密金鑰預設無法匯出。
Import-PfxCertificate除非指定-Exportable,否則匯入後的私密金鑰無法重新匯出。這不是事故,而是理想的預設值。6 - 到期問題要靠盤點自動化來防止。像
Get-ChildItem Cert:\LocalMachine\My -ExpiringInDays 60這樣,可以機械化地抓出將在指定天數內到期的憑證。4 - 把指紋(拇印)寫死在程式碼或組態裡,每次憑證更新都會出事。因為新憑證的指紋一定會改變。把設定外部化+保留新舊並行期間,是設計上的基本原則(第 5、7 章)。
2. 憑證存放區的全貌 ── 兩個位置與邏輯存放區
2.1. 使用者與電腦兩大體系
Windows 的憑證存放區,大致分成兩個「位置」。1
- 電腦(本機電腦,LocalMachine)的憑證存放區:一台 PC 只有一份,所有使用者與服務共用。實體位於登錄檔的
HKEY_LOCAL_MACHINE\Software\Microsoft\SystemCertificates之下。2 - 使用者(現在使用者,CurrentUser)的憑證存放區:每個使用者帳戶各自獨立。實體位於
HKEY_CURRENT_USER\Software\Microsoft\SystemCertificates之下,也就是使用者設定檔的一部分。2
除此之外還有以服務帳戶為單位的存放區3,實體是各服務名稱底下的登錄機碼。2 實務上首先要掌握的是前面這兩種。
有一項重要規格必須先了解。使用者存放區中除了「個人」以外的每個邏輯存放區,都會繼承並顯示電腦存放區同名存放區的內容。1 例如把公司內部 CA 的憑證放進電腦存放區的「信任的根憑證授權單位」,這張憑證也會出現在所有使用者的「信任的根憑證授權單位」中。反過來說,唯獨「個人」存放區不會被繼承,所以用戶端憑證(放進個人存放區的東西)「需要被誰看到」,必須自己決定。這種不對稱性,是本文全篇的主角。
flowchart TB
subgraph LM["電腦-LocalMachine,PC 只有一份,全體使用者與服務共用"]
LMMY["個人-My"]
LMROOT["信任的根憑證授權單位-Root"]
LMCA["中繼憑證授權單位-CA"]
LMTP["信任的發行者-TrustedPublisher"]
end
subgraph CU["使用者-CurrentUser,依帳戶各自獨立"]
CUMY["個人-My,※不會被繼承,需自行決定放置位置"]
CUROOT["信任的根憑證授權單位-Root"]
CUCA["中繼憑證授權單位-CA"]
CUTP["信任的發行者-TrustedPublisher"]
end
LMROOT -.->|"內容會被繼承顯示"| CUROOT
LMCA -.->|"繼承"| CUCA
LMTP -.->|"繼承"| CUTP
2.2. 主要的邏輯存放區
每個位置底下,又分成依角色區分的邏輯存放區。這正是 certmgr.msc/certlm.msc 中看到的資料夾,從 PowerShell 或指令查看時要使用英文內部名稱。24
| 顯示名稱 | 內部名稱 | 放置什麼 |
|---|---|---|
| 個人 | My | 自己(這台 PC・這個使用者)要用的憑證。用戶端憑證・伺服器憑證都放這裡。與私密金鑰建立關聯的也是這裡 |
| 信任的根憑證授權單位 | Root | 作為信任起點的根 CA 憑證。放進這裡的 CA 底下都會被「信任」 |
| 中繼憑證授權單位 | CA | 連接根與末端之間的中繼 CA 憑證。是建立憑證鏈結的材料 |
| 信任的發行者 | TrustedPublisher | 信任已簽署軟體發行者的憑證(第 8 章) |
2.3. 三個觀察窗 ── certmgr.msc/certlm.msc/Cert: 磁碟機
- certmgr.msc:開啟目前使用者存放區的管理主控台。
- certlm.msc:開啟本機電腦存放區的管理主控台。
- PowerShell 的
Cert:磁碟機:能以Cert:\CurrentUser\...與Cert:\LocalMachine\...的階層結構,像操作檔案系統一樣操作存放區。憑證以指紋識別。
另外,若手動在 mmc.exe 中新增憑證嵌入式管理單元,需要從「使用者帳戶」「電腦帳戶」「服務帳戶」三種對象中選擇。非系統管理員的使用者只能管理自己使用者帳戶的存放區。3
排除故障時的第一步,是讓「應用程式看的是哪個存放區」與「自己看的是哪個存放區」一致。一邊盯著 certmgr.msc、一邊調查服務的故障,因為看的位置根本不同,永遠不會有答案。
3. 該放進哪個存放區 ── 依程式的執行形態決定的判斷表
判斷基準只有一個。使用這張憑證的程式,是以誰的帳戶執行?
| 執行形態 | 執行帳戶 | 放進的存放區 | 備註 |
|---|---|---|---|
| 互動使用者啟動的桌面應用程式 | 登入使用者本人 | 使用者(Cert:\CurrentUser\My) | 需要依使用者帳戶逐一佈署。若是多人共用的 PC,也可考慮改放電腦存放區 |
| Windows 服務 | LocalSystem/NETWORK SERVICE/專用服務帳戶 | 電腦(Cert:\LocalMachine\My) | 非 LocalSystem(NETWORK SERVICE・專用帳戶等)必須授予私密金鑰讀取權限(第 4 章)。LocalSystem 以預設的 SYSTEM 權限即可讀取 |
| IIS 上的 Web 應用程式 | 應用程式集區的識別 | 電腦 | 同上 |
| 工作排程器的無人值守執行(不論使用者是否登入都會執行) | 工作中指定的帳戶 | 建議放電腦 | 也能放在執行帳戶的使用者存放區運作,但只會增加設定檔與存放區顯示方式的驗證成本,好處不大 |
| 瀏覽器上的電子申請・Web 驗證 | 登入使用者本人 | 使用者 | 從「不讓配發對象以外的人使用」的角度來看也很自然 |
拿不定主意時,無人執行的放電腦存放區,人操作的放使用者存放區。
3.1. 常見事故解剖 ── 「開發時期能動、改成服務後卻找不到」
這個事故,可以照下面的步驟精準重現。
- 開發人員在自己的 PC 上,雙擊 pfx 進行匯入。精靈的預設值是「現在使用者」,所以憑證會放進開發人員帳戶的使用者存放區。
- 開發中的應用程式從 Visual Studio 啟動,也就是以開發人員帳戶執行,所以開啟
StoreLocation.CurrentUser就能找到憑證。可以運作。 - 在正式環境伺服器上,把應用程式註冊為 Windows 服務。服務以 NETWORK SERVICE 或專用帳戶執行。
- 服務程式碼開啟的
CurrentUser,指的是服務執行帳戶的使用者存放區。那裡是空的。「找不到憑證」。
flowchart TB
subgraph DEV["開發機"]
D1["雙擊 pfx 進行匯入<br/>精靈預設為現在使用者"] --> D2["放進開發人員帳戶的<br/>使用者存放區"]
D2 --> D3["從 Visual Studio 執行<br/>=以開發人員帳戶運作"]
D3 --> D4["開啟 CurrentUser 就能找到<br/>→ 可以運作"]
end
subgraph PROD["正式環境伺服器"]
P1["註冊為 Windows 服務<br/>執行帳戶為 NETWORK SERVICE 等"] --> P2["程式碼開啟的 CurrentUser 是<br/>服務帳戶的使用者存放區"]
P2 --> P3["那裡是空的<br/>→ 找不到憑證"]
end
D4 -.->|"部署相同的程式"| P1
重點在於使用者存放區「有多少帳戶就有多少份」。就算系統管理員開啟 certmgr.msc 確認「不是好好裝著嗎?」,那也只是系統管理員自己的存放區,不是服務帳戶的存放區。正確的處理方式不是臨時複製,而是重新放進電腦存放區,程式碼也一併改成 StoreLocation.LocalMachine。而且緊接下一章的權限授予,也必須一併完成。
4. 私密金鑰與存取權限 ── 第二種常見事故
4.1. 憑證和私密金鑰是不同的東西
憑證存放區清單中看到的是憑證(公開資訊),並不是私密金鑰本身。用戶端驗證實際需要的是使用私密金鑰的簽署處理,所以「清單看得到」和「能不能用」是兩回事。混淆這兩者,就會發生「明明有憑證卻在 TLS 交握失敗」「出現拒絕存取類的內部錯誤」這種外觀上很難判斷的故障。
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 應用程式不要把機密資訊以明文存進設定檔的最佳實踐」與「PowerShell 中安全處理認證資訊」中。
4.3. 授予服務帳戶私密金鑰權限
放進電腦存放區的憑證,其私密金鑰在預設情況下,通常只有系統管理員與 SYSTEM 能讀取。因此,以 LocalSystem 執行的服務在預設狀態下就能讀取私密金鑰,但如果是 NETWORK SERVICE、專用服務帳戶、IIS 應用程式集區識別等其他帳戶執行的情況,就必須明確授予執行帳戶讀取權限。步驟可以在憑證嵌入式管理單元的 UI 中完成。5
- 開啟 certlm.msc(或以電腦帳戶為對象的憑證嵌入式管理單元)。
- 在「個人」→「憑證」中,於目標憑證按右鍵,從「所有工作」開啟「管理私密金鑰」。
- 在「安全性」索引標籤中新增執行帳戶(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. 更換的步驟 ── 新舊並行期間與指紋陷阱
憑證更新不是「先刪除再放入」,而是「先新增,切換後再確認,最後才刪除」。
- 把新憑證(pfx)匯入同一個存放區。因為指紋不同,新舊憑證可以在同一個存放區中共存。
- 授予新憑證的私密金鑰權限(第 4 章)。更新時最容易忘記的就是這一步。權限是依憑證的私密金鑰各自附加的,所以憑證換了,權限授予也要重做一次。
- 若對方系統需要事先登錄憑證,就在維持以舊憑證運作的狀態下先完成登錄,確保新舊憑證都能被接受的並行期間。若先切換再登錄,對方可能會拒絕新憑證,導致正式環境通訊中斷。
- 把應用程式組態切換到新憑證,並確認運作。
- 經過足夠的並行期間後,刪除舊憑證。
flowchart LR
I["1. 將新 pfx 匯入至同一存放區<br/>新舊並存"] --> P["2. 授予新憑證的<br/>私密金鑰權限"]
P --> R["3. 向對方系統事先登錄<br/>以舊憑證維持運作"]
R --> SW["4. 改寫組態中的指紋<br/>並切換、確認運作"]
SW --> DEL["5. 並行期間結束後<br/>刪除舊憑證"]
這時最大的陷阱,是寫在組態檔或程式碼中的指紋。指紋是每張憑證各自獨有的,所以更新後一定會改變。只要有一個地方仍參照舊指紋,就會出現「憑證明明更新了卻連不上」的情況。用台帳管理指紋寫在哪些地方(應用程式組態、IIS 繫結、指令碼、對方系統的登錄資訊),才是可靠的做法。
5.3. 建議建立憑證台帳
台帳並不需要多複雜,一開始一份 Excel 就足夠。至少建立用途/發行者/主體/指紋/存放位置(伺服器名稱+存放區)/擁有私密金鑰權限的帳戶/有效期限/更新步驟的連結/負責人這些欄位,並與 5.1 的盤點結果核對。憑證事故的本質不是技術問題,而是「沒有人手上有清單」的問題,所以台帳最能發揮效果。
6. 驗證與失敗的解讀 ── 憑證鏈結與根憑證部署
6.1. 憑證鏈結驗證的基本與 certutil
「這個憑證不受信任」這類錯誤,代表從末端憑證到根 CA 之間的憑證鏈結(憑證路徑)在某處中斷了。可以用 certutil 來排查。7
flowchart TB
LEAF["末端憑證<br/>用戶端憑證・伺服器憑證"] --> INT["中繼 CA 憑證<br/>存放位置-中繼憑證授權單位-CA 存放區"]
INT --> ROOT["根 CA 憑證<br/>存放位置-信任的根憑證授權單位-Root"]
INT -.->|"無法取得<br/>提示・AIA・存放區皆無"| E1["無法建立憑證鏈結<br/>常見原因 1"]
ROOT -.->|"未部署"| E2["出現不受信任錯誤<br/>常見原因 2"]
LEAF -.->|"已過期"| E3["有效期間錯誤<br/>常見原因 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 或驗證用的自我簽署憑證,就需要把它的根憑證部署到每台 PC。不要一台一台手動放入,而是要納入部署機制。
- Active Directory 環境(GPO):把憑證匯入群組原則的「電腦設定\原則\Windows 設定\安全性設定\公開金鑰原則」下的「信任的根憑證授權單位」,就會部署到目標 PC。8
- Intune 管理環境:用「受信任的憑證」設定檔部署根/中繼 CA 憑證。在 Windows 上可以選擇部署目的地存放區(電腦的根/中繼、使用者的中繼)。9
如同 2.1 所述,只要放進電腦存放區的根憑證存放區,就會被所有使用者信任。1 正因如此,也要正視相反的風險。把自我簽署憑證放進「信任的根憑證授權單位」的做法,等於在這台 PC 上種下一個新的信任起點。一旦這張憑證的私密金鑰外流,就會成為簽發冒充任意網站或軟體的憑證的立足點。若要當作長期運作方式,正確做法是建立好好保護私密金鑰的公司內部 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 的第三個參數 validOnly。設為 true 只會回傳通過驗證的有效憑證。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 把公司內部發布應用程式的發行者,部署到每台 PC 的 TrustedPublisher。
若您是「發布應用程式的一方」,需要處理程式碼簽署或 SmartScreen 警告(「Windows 已保護您的電腦」)的話,另一篇文章「Windows 為什麼會出現「Windows 已保護您的電腦」」有完整整理。本文的知識(存放區的兩大體系、根憑證部署)可以直接作為那篇文章的前提知識使用。
總結
- 憑證存放區分成使用者(CurrentUser)與電腦(LocalMachine)兩大體系。certmgr.msc/certlm.msc/
Cert:磁碟機是觀察同一件事的三個窗口。調查的第一步,是先確認「談的是哪個存放區」。 - 放置位置由「程式以誰的身分執行」決定。無人執行(服務・IIS・工作)放電腦存放區,互動應用程式放使用者存放區,是基本原則。
- 「開發時期能動、正式環境卻找不到」,原因是開發人員的使用者存放區與服務帳戶的使用者存放區是不同的東西。改成電腦存放區+
StoreLocation.LocalMachine就能解決。 - 放進電腦存放區,與在「管理私密金鑰」中授予讀取權限,永遠是一組動作。更新時也別忘了重新授予。
- pfx 匯入預設無法匯出。
-Exportable只在真正需要時才使用。原始 pfx 與密碼的保管,也要納入設計範圍。 - 過期問題要靠
Get-ChildItem Cert: ... -ExpiringInDays的定期盤點與憑證台帳來防止。更換順序是「新增→切換→確認→刪除」,注意組態中指紋是否有遺漏更新。 - 憑證鏈結的排查用
certutil -urlfetch -verify。公司內部 CA 的根憑證要用 GPO/Intune 部署,把自我簽署憑證放進根存放區的做法,僅限驗證環境使用並設定有效期限。 - 程式碼中把指紋外部化到組態,並記錄選到的憑證。光是這樣,憑證引起的故障處理就會大不相同。
相關文章
- Windows 為什麼會出現「Windows 已保護您的電腦」
- Windows 應用程式不要把機密資訊以明文存進設定檔的最佳實踐
- PowerShell 中安全處理認證資訊 ── 把明文密碼逐出腳本
- 不要用 using 包住 HttpClient ── C# 商用應用程式的 HTTP 通訊實務(生成模式・逾時・重試)
- 刷My Number保險證會發生什麼事 ── 從ORCA原始碼解讀線上資格確認與收費電腦的串接
相關諮詢領域
合同會社小村軟體處理搭配用戶端憑證的 Web API 串接(銀行系 API、線上資格確認等)的業務應用程式開發、「找不到憑證」「更新後連不上」這類故障調查,以及憑證更換步驟的整理。就算目前還處於「不知道該看存放區的哪裡」的階段,也歡迎諮詢。
參考連結
-
Microsoft Learn, Local Machine and Current User Certificate Stores。關於電腦的憑證存放區對這台 PC 而言是本機的、且所有使用者共用、位於 HKEY_LOCAL_MACHINE 之下,使用者的憑證存放區依使用者帳戶各自獨立、位於 HKEY_CURRENT_USER 之下,以及使用者存放區除「個人」存放區以外會繼承電腦存放區的內容(新增到電腦「信任的根憑證授權單位」的憑證,也會出現在每個使用者的同一存放區中)的說明。 ↩ ↩2 ↩3 ↩4
-
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
-
Microsoft Learn, How to: View certificates with the MMC snap-in。關於 certlm.msc 用於管理本機裝置(本機電腦)的憑證、certmgr.msc 用於管理目前使用者的憑證,憑證嵌入式管理單元的對象有「電腦帳戶」「使用者帳戶」「服務帳戶」三種,以及非系統管理員的使用者只能管理自己使用者帳戶憑證的說明。 ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, about_Certificate_Provider。關於 PowerShell 的 Cert: 磁碟機是擁有 CurrentUser 與 LocalMachine 兩個存放區位置的階層式命名空間、可用 Get-ChildItem 列舉存放區與憑證、-ExpiringInDays 參數會回傳將在指定天數內到期的憑證(0 則為已過期)、-CodeSigningCert 等動態參數、NotAfter 屬性存放有效期限,以及憑證以指紋識別的說明。 ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, How to Modify Private Key Permissions to Support Management Server or Streaming Server。關於在以本機電腦憑證存放區為對象的憑證嵌入式管理單元中開啟「管理私密金鑰」(Manage Private Keys),並在「安全性」索引標籤中為服務執行帳戶(例如 Network Service)新增「讀取」存取權限的步驟說明。 ↩ ↩2 ↩3
-
Microsoft Learn, Import-PfxCertificate。關於 Import-PfxCertificate 會把 PFX 檔案中的憑證與私密金鑰匯入指定存放區、未指定 -Exportable 開關時匯入的私密金鑰無法匯出,以及 -CertStoreLocation・-Password・-FilePath 各參數的語法與使用範例的說明。 ↩ ↩2 ↩3
-
Microsoft Learn, certutil。關於 certutil -verify 會驗證憑證・CRL・憑證鏈結,未指定 CA 憑證檔案時會建立完整鏈結並驗證、可使用 -urlfetch 選項,以及 certutil -store 會傾印憑證存放區、加上 -user 選項可改為存取使用者存放區而非電腦存放區的說明。 ↩ ↩2
-
Microsoft Learn, Distribute Certificates to Client Computers by Using Group Policy。關於把憑證匯入群組原則「電腦設定\原則\Windows 設定\安全性設定\公開金鑰原則」底下的「信任的根憑證授權單位」,藉此部署到網域內用戶端電腦的步驟,以及所需權限(相當於 Domain Admins/Enterprise Admins)的說明。 ↩
-
Microsoft Learn, Create trusted certificate profiles in Microsoft Intune。關於 Intune 的「受信任的憑證」設定檔是把根或中繼 CA 憑證部署到受管理裝置的機制、作為 SCEP/PKCS 憑證設定檔前提用來建立對根 CA 的信任,以及在 Windows 上可選擇的部署目的地存放區包含「電腦憑證存放區-根」「電腦憑證存放區-中繼」「使用者憑證存放區-中繼」的說明。 ↩
-
Microsoft Learn, X509Store Class。關於 X509Store 可用 StoreName 與 StoreLocation(CurrentUser/LocalMachine)建構、用 Open 方法與 OpenFlags(ReadOnly、OpenExistingOnly 等)開啟存放區、用 Certificates 屬性取得憑證集合,標準存放區名稱包含 My・Root・CA・TrustedPublisher 等,以及 TrustedPublisher 存放區在 CurrentUser・LocalMachine 兩個位置都存在的說明。 ↩ ↩2
-
Microsoft Learn, X509Certificate2Collection.Find(X509FindType, Object, Boolean) Method。關於 Find 方法會依 X509FindType(FindByThumbprint 等)與搜尋值搜尋憑證,第三個參數 validOnly 指定 true 時只會回傳通過驗證的有效憑證的說明。 ↩ ↩2
-
Microsoft Learn, HttpClientHandler.ClientCertificates Property。關於 ClientCertificates 屬性是以憑證為基礎的用戶端驗證中提示給伺服器的 X509CertificateCollection,以及 .NET Core 中若憑證存在金鑰使用方式屬性,必須包含「Digital Signature」的說明。 ↩ ↩2
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
Windows 防火牆與業務應用程式 ── 受信規則要在安裝程式中登錄
「開發機上正常運作,但在客戶端卻無法通訊」的典型原因就是 Windows 防火牆。本文說明受信預設封鎖與設定檔的機制、為何不能把正式環境交給通知對話方塊處理,以及在安裝程式中登錄受信規則與問題排查的步驟。
PowerShell 的安全性強化 ── 日誌・AMSI・語言模式・JEA
本文整理在不禁止 PowerShell 的前提下安全使用它的實務做法。內容涵蓋啟用指令碼區塊記錄與逐字稿記錄、停用 AMSI 與舊版本、以語言模式進行限制,以及透過 JEA 委派權限。
磁碟區陰影複製服務(VSS)的機制與實務 ── 為什麼能備份使用中的檔案
明明使用中的檔案會因共用違規而無法複製,備份軟體卻為什麼辦得到?本文解說磁碟區陰影複製服務(VSS)中要求者・寫入器・提供者的角色分工、寫入時複製的機制、vssadmin 的實務操作與差異區的陷阱。
在 C#・PowerShell 中使用 WMI/CIM ── 硬體資訊取得・處理程序監控・遠端查詢的實務指南
取得 PC 序號、監控磁碟可用空間、偵測處理程序啟動,這些定番需求的標準答案就是 WMI/CIM。本文解說 Get-CimInstance 等 CIM Cmdlet 的用法、從舊版 Get-WmiObject 的遷移方式、C# 的 System.Management 與 C...
群組原則(GPO)實務入門 ── 運作機制、生效確認與 Intune 的分工
你是否在不清楚「用 GPO 分發」是什麼意思的情況下,就在操作 AD 環境?本文從實務角度說明群組原則的運作機制與 LSDOU 套用順序、以 gpupdate、gpresult 確認生效狀況、與 Intune 的分工,以及客戶端 GPO 改變應用程式行為的陷阱。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
常見問題
整理諮詢這個主題時常見的問題。
- certmgr.msc 和 certlm.msc 有什麼不同?
- 差異在於對象存放區不同。certmgr.msc 開啟的是目前登入使用者的憑證存放區(現在使用者,CurrentUser),certlm.msc 開啟的是電腦的憑證存放區(本機電腦,LocalMachine)。電腦存放區是這台 PC 上所有使用者與服務共用的,管理它需要系統管理員權限。非系統管理員的使用者只能管理自己的使用者存放區。兩者內部都分成「個人」「信任的根憑證授權單位」等邏輯存放區,從 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 則會列出已經過期的憑證。把這個查詢做成每月對全部伺服器執行一次的例行作業,並將結果與憑證台帳核對,幾乎就能防止「因憑證過期,一早開始就無法連線」這類事故。