前言

這篇文章是我在開發 gRPC + Kestrel 專案時,遇到 SSL 憑證問題後整理的學習筆記。

如果你跟我一樣,正在用 .NET 的 Kestrel 當作 gRPC Server,並且想要啟用 HTTPS 加密連線,那你一定會遇到一個問題:怎麼產生一張測試用的憑證?

這篇文章會從觀念開始講起,一步一步帶你走完整個流程。


目錄


觀念篇:為什麼是 Server 要有憑證?

這是我學習時最容易搞混的地方。

我們直覺會覺得:「我是客戶端 (UI),我要連到伺服器 (Server),應該是我拿出證件證明『我是誰』才對吧?」

但在 HTTPS/TLS 的世界裡,邏輯是反過來的。

詐騙集團 vs. 真銀行

想像你的 UI (前端) 是一輛運鈔車,你的 Server (後端) 是一間銀行金庫。你要把錢 (資料) 運進去。

角色 比喻 驗證目的
Server 銀行金庫 出示「營業執照 (憑證)」證明自己是真的銀行
Client 運鈔車 在連線建立後,透過帳號密碼/Token 證明身份

運鈔車司機最怕什麼? 怕開錯地方,把錢交給假扮成銀行的詐騙集團!

所以 銀行 (Server) 必須在大門口掛一張「政府核發的營業執照 (憑證)」。運鈔車司機 (UI) 遠遠開過來,先拿望遠鏡看那張執照:「嗯,這是真的銀行,不是假佈景。」確認安全後,運鈔車才敢開過去建立連線。


gRPC 自簽憑證概念圖


SSL Handshake 流程

sequenceDiagram participant C as UI (Client) participant S as Server C->>S: 嗨,我想跟你建立安全連線!(Client Hello) S->>C: 好的!這是我的身分證 (Certificate) 和公鑰 (Server Hello) C->>C: 檢查指紋... 嗯,指紋對了,你是真的 Server C->>S: 我用你的公鑰把資料鎖起來傳給你

什麼時候 Client 才需要憑證?

如果你有這個疑問,那叫做 雙向驗證 (mTLS, Mutual TLS)。軍方系統或銀行內部核心系統會用這種方式,要求雙方都出示憑證。

但在一般應用程式開發非常少見,因為管理太麻煩了 (每台 Client 電腦都要裝憑證)。


簡單記法: HTTPS 就像是 Server 開了一家店,它要把「營業執照 (憑證)」掛在門口給你看,你才敢進去消費。



工具篇:PowerShell vs. IIS 管理介面

這是一個經典的「CLI (指令列) vs GUI (圖形介面)」的問題。


核心差異比較

特性 PowerShell IIS 管理介面
精準度 ⭐⭐⭐⭐⭐ 極高 ⭐⭐ 低
自訂功能 可自訂過期日 (5年)、多網域 (SAN)、密碼強度 幾乎無法自訂 (預設 1 年)
環境需求 Windows 內建 (不需安裝額外功能) 必須安裝 IIS (Web Server) 才能用
自動化 ✅ 可寫成腳本一鍵執行 ❌ 必須手動點擊滑鼠
主要用途 開發人員、DevOps 自動化 網管人員 (SysAdmin) 快速設定

為什麼 IIS 介面不適合 gRPC 專案?


致命傷 A:缺了「主體別名 (SAN)」

  • IIS 做出來的: 通常只會設定 Subject = localhost
  • 現代標準: Chrome 和 .NET Core 預設已經不看 Subject 了,它們看的是 SAN (Subject Alternative Name)
  • 結果: gRPC Client 連線時還是噴錯「憑證無效」

PowerShell 指令裡的 -DnsName "localhost", "127.0.0.1" 就是在設定 SAN。

致命傷 B:殺雞焉用牛刀

你的架構是 Kestrel (WinForm 裡面的自宿主 Server)。

為了產生一張憑證,特地去 Windows 功能裡安裝龐大的 IIS (Internet Information Services),這就像為了喝一杯牛奶養了一頭牛。

結論: 現代化的 .NET Core gRPC 跑在 Kestrel 上,PowerShell 是你的唯一正解



實戰篇:產生測試憑證 (PFX)


第一步:執行 PowerShell 腳本

  1. 在 Windows 開始選單搜尋 PowerShell
  2. 右鍵「以系統管理員身分執行」
  3. 複製下面這整段程式碼,貼進 PowerShell 視窗並按下 Enter
# --- 設定參數區 ---
$pfxPassword = "m1234"
$pfxFileName = "server_cert.pfx"
$friendlyName = "[Dev_Cert_DoNotTrust]"
$outputDir = "C:\Temp\LCerts"
# -----------------

# 1. 建立暫存資料夾
if (!(Test-Path $outputDir)) { 
    New-Item -ItemType Directory -Path $outputDir | Out-Null 
}

$pfxPath = Join-Path $outputDir $pfxFileName
Write-Host "正在製造測試用的營業執照..." -ForegroundColor Cyan

# 2. 產生自簽憑證
$cert = New-SelfSignedCertificate `
    -DnsName "localhost", "127.0.0.1" `
    -CertStoreLocation "Cert:\CurrentUser\My" `
    -FriendlyName $friendlyName `
    -KeyExportPolicy Exportable `
    -KeySpec KeyExchange `
    -NotAfter (Get-Date).AddYears(5)

# 3. 匯出成 .pfx
$passwordSecure = ConvertTo-SecureString $pfxPassword -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath $pfxPath -Password $passwordSecure

# 4. 顯示結果
Write-Host "`n★ 成功!憑證已產生!" -ForegroundColor Green
Write-Host "檔案位置: $pfxPath" -ForegroundColor Yellow
Write-Host "檔案密碼: $pfxPassword" -ForegroundColor Yellow
Write-Host "指紋 (Thumbprint): $($cert.Thumbprint)" -ForegroundColor Magenta

第二步:部署到專案

  1. 打開你的 Visual Studio 專案資料夾
  2. 在後端專案裡,建立 Config 資料夾
  3. C:\Temp\Certs\server_cert.pfx 複製進去
  4. 在 Visual Studio 裡:
    • 點選 .pfx 檔案
    • 在「屬性」視窗,找到 「複製到輸出目錄」
    • 改為 「如果有更新則複製」

第三步:更新設定檔

後端 Config:

UseSsl = true
CertPath = @".\Config\server_cert.pfx"
CertPassword = "m1234"

前端 Config:

UseSsl = true
AllowInsecure = false
Thumbprint = (貼上 PowerShell 顯示的指紋)



前端篇:設定指紋驗證

觀念解鎖:為什麼前端不需要 PFX 檔案?

「PFX 檔案當然有指紋,但前端不需要 PFX 檔案,前端只需要知道那串『指紋號碼』就好。」

想像你是 「演唱會驗票員 (前端 Client)」,而後端 Server 是 「持有 VIP 票的觀眾」

  • 後端 (Server): 手上有 VIP 門票正本 (PFX 檔案)
  • 前端 (Client): 手上有主辦單位給的清單,寫著「今天的 VIP 票號碼是 A1B2C3... (指紋)」

當後端走過來出示他的票,你只要看一眼他的票號跟清單一樣,就放行。


實作步驟


找出指紋

如果關掉了 PowerShell 視窗,用這個指令再查一次:

Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.FriendlyName -like "*LCS*" }

設定前端 Config

打開 ConnectionList.xml

<ConnectionInfo   
    Name="Local_Dev_Secure"  
    Ip="127.0.0.1"   
    Port="5006"   
    UseSsl="true"   
    AllowInsecure="false"   
    Thumbprint="A1B2C3D4E5F678901234567890ABCDEF12345678" />
屬性 說明
UseSsl="true" 告訴運鈔車要走 HTTPS 通道
AllowInsecure="false" 告訴運鈔車要嚴格驗證
Thumbprint="..." 告訴運鈔車只准讓拿這張身分證的人進來


清理篇:刪除測試憑證

測試完懂得把垃圾帶走,保持開發環境的潔淨,這才是有潔癖的高級工程師該有的素養。

方法一:PowerShell 光速滅證 (推薦)

# --- 設定區 ---
$targetFriendlyName = "[Dev_Cert_DoNotTrust]"
$tempPfxPath = "C:\Temp\Certs\server_cert.pfx"
# --------------

Write-Host "正在搜尋並移除測試憑證..." -ForegroundColor Cyan

# 1. 清除 Windows 憑證存放區
$certs = Get-ChildItem -Path "Cert:\CurrentUser\My" | Where-Object { $_.FriendlyName -eq $targetFriendlyName }

if ($certs) {
    foreach ($c in $certs) {
        Remove-Item -Path $c.PSPath
        Write-Host "✅ 已從 Windows 存放區移除憑證: $($c.Thumbprint)" -ForegroundColor Green
    }
} else {
    Write-Host "⚠️ 在存放區找不到該憑證" -ForegroundColor Yellow
}

# 2. 清除暫存檔案
if (Test-Path $tempPfxPath) {
    Remove-Item -Path $tempPfxPath -Force
    Write-Host "✅ 已刪除暫存檔案: $tempPfxPath" -ForegroundColor Green
}

Write-Host "`n電腦回復乾淨狀態!" -ForegroundColor Cyan

方法二:手動介面刪除

  1. 按下 Win + R,輸入 certmgr.msc,按 Enter
  2. 左側展開 「個人 (Personal)」「憑證 (Certificates)」
  3. 找到「發給」是 localhost,「好記名稱」是 [Dev_Cert_DoNotTrust] 的那張
  4. 右鍵 → 刪除

方法三:清理專案裡的殘留

別忘了刪除專案目錄裡的 Config\server_cert.pfx

PowerShell 腳本只會刪除 C:\Temp 裡的原始檔,不會動專案裡的那份複製品。



總結

步驟 說明
1 理解憑證是給 Server 用的
2 用 PowerShell 產生自簽憑證
3 把 .pfx 複製到後端專案
4 把指紋貼到前端設定檔
5 測試完記得清理環境

現在,你的後端就是一家持有合法 (測試用) 執照的銀行,而你的前端就是拿著正確指紋驗證碼的運鈔車。

按下 F5 啟動吧!


  • first edition time: 2026-01-31
這是一份還在成長中的文章,會持續更新,歡迎訂閱追蹤我的部落格獲取最新資訊!