以下為基於文章內容所萃取並結構化的 15 個教學型解決方案案例。每個案例均包含問題、根因、完整解法(含程式碼/流程)、效益與練習評估,適合用於實戰教學與專案演練。
Case #1: 跨服務信任建立:以 RSA 簽章的 API Token
Problem Statement(問題陳述)
- 業務場景:在微服務/服務導向場景中,使用者於 A 服務完成付費或驗證後,需要前往 B 服務消費或使用 API,但 A 與 B 不具備即時、安全的互通管道(跨網域、跨組織、不同運維團隊)。需要一種在不直接呼叫 A 的情況下,讓 B 能信任使用者資訊與權限的機制。
- 技術挑戰:如何確保資料未被竄改且來源可信?如何避免每次驗證都回呼 A 而造成高延遲與單點瓶頸?
- 影響範圍:所有跨服務的授權與交易流程、API 安全、營運成本與使用者體驗。
- 複雜度評級:中
Root Cause Analysis(根因分析)
- 直接原因:
- 缺乏跨服務的信任傳遞機制,B 無法確認 A 所簽發的資訊真偽。
- 網路不安全(公開網際網路),傳輸資料可能遭竊聽或竄改。
- 實時調 A 驗證增加耦合與延遲。
- 深層原因:
- 架構層面:缺少去中心化信任設計,依賴同步授權查詢。
- 技術層面:未使用非對稱密碼學(RSA)與數位簽章來保證完整性與來源。
- 流程層面:授權資訊未標準化為可攜帶的安全票據(Token)。
Solution Design(解決方案設計)
-
解決策略:在 A 使用私鑰對授權資料簽章,B 保存 A 的公鑰,對來自客戶端攜帶的 Token 進行驗證(VerifyData)。驗證成功即可離線信任內容,避免回呼 A,達成去中心化、低耦合的跨服務信任。
- 實施步驟:
- 產生與管理金鑰
- 實作細節:A 保存 RSA Private Key;B 保存對應 Public Key。
- 所需資源:RSACryptoServiceProvider/RSACng、憑證或金鑰管理。
- 預估時間:0.5 天。
- 設計 Token 資料結構
- 實作細節:以 TokenData(含 ExpireDate、TypeName 等)表示可攜授權資料。
- 所需資源:C#、Newtonsoft.Json/BSON。
- 預估時間:0.5 天。
- 在 A 簽發 Token
- 實作細節:序列化資料、SignData 後打包(data + signature)。
- 所需資源:TokenHelper.EncodeToken。
- 預估時間:0.5 天。
- 在 B 驗證 Token
- 實作細節:VerifyData、反序列化、IsValidate 驗證。
- 所需資源:TokenHelper.DecodeToken。
- 預估時間:0.5 天。
- 產生與管理金鑰
- 關鍵程式碼/設定: ```csharp // 產生 Token(A 端) public static string EncodeToken(string keyName, TokenData token) { // 序列化 (BSON) byte[] data = SerializeBson(token); // RSA 私鑰簽章 byte[] sig = _RSACSP_STORE[keyName].SignData(data, _HALG); // 打包:Base64(data) + ‘.’ + Base64(sig) return $”{Convert.ToBase64String(data)}.{Convert.ToBase64String(sig)}”; }
// 驗證 Token(B 端)
public static T DecodeToken
- 實際案例:文章中的 AUTH 專案負責簽發 SessionToken;API 專案負責驗證並執行服務。
- 實作環境:ASP.NET Web API 2、.NET Framework、Newtonsoft.Json + BSON、RSA(RSACryptoServiceProvider)。
- 實測數據:
- 改善前:B 每次需同步調 A 驗證(1 次網路往返/請求)。
- 改善後:B 本地驗證(0 次網路往返/請求)。
- 改善幅度:驗證延遲降低約 20~50ms/請求(示範網路環境),耦合度顯著降低。
- Learning Points(學習要點)
- 核心知識點:
1. 非對稱密碼學與數位簽章。
2. 去中心化信任模型。
3. Token 攜帶授權的設計思路。
- 技能要求:
- 必備技能:C#、基本 RSA/Hash 概念、ASP.NET Web API。
- 進階技能:金鑰管理與部署、自動化測試。
- 延伸思考:
- 適用於 BFF、API Gateway 後端服務信任;跨組織資料交換。
- 風險:私鑰外洩;需完善金鑰輪替。
- 優化:採用 JWT 標準與 Key Vault 代管。
- Practice Exercise(練習題)
- 基礎練習:以 RSA 產生一對金鑰,實作最小可用的簽章/驗章流程(30 分鐘)。
- 進階練習:把授權資料包成 Token,在 A 簽發、B 驗證並以授權結果控制 API 行為(2 小時)。
- 專案練習:建置 AUTH + API 兩專案,完成購買後發券與入場驗券的端到端流程(8 小時)。
- Assessment Criteria(評估標準)
- 功能完整性(40%):完成 A 簽發、B 驗證與授權控制。
- 程式碼品質(30%):模組化、測試覆蓋率、錯誤處理清晰。
- 效能優化(20%):驗證延遲、序列化效率。
- 創新性(10%):擴展性設計(多服務、多金鑰)。
---
## Case #2: 數位簽章驗證資料完整性與來源
### Problem Statement(問題陳述)
- 業務場景:B 服務需確認從 A 服務來的授權內容未被竄改且確實由 A 簽發,以避免用戶在客戶端修改數量/金額/權限造成損失。
- 技術挑戰:在不安全的網路環境中,如何可靠判斷資料完整性與來源身份。
- 影響範圍:訂單、支付、權限控制、審計合規。
- 複雜度評級:中
### Root Cause Analysis(根因分析)
- 直接原因:
1. 沒有簽章,無法檢測資料被改動。
2. 沒有來源驗證,可能被冒名發送。
3. 客戶端可見資料隨意修改。
- 深層原因:
- 架構層面:缺乏不可抵賴的簽章流程。
- 技術層面:不懂 Hash 與簽章的配合。
- 流程層面:授權資料缺少驗證步驟。
### Solution Design(解決方案設計)
- 解決策略:將資料計算 Hash,再以 A 的私鑰簽章為 signature;B 以公鑰解鎖 signature 得到 Hash,再自己重算 Hash2 比對,若一致則資料未被竄改且來源可信。
- 實施步驟:
1. 介面定義與封裝
- 實作細節:封裝 SignData/VerifyData 流程,統一入口。
- 所需資源:.NET RSA API。
- 預估時間:0.5 天。
2. 驗證流程整合
- 實作細節:B 端中間件統一驗證,避免重覆程式碼。
- 所需資源:Web API DelegatingHandler/Filter。
- 預估時間:1 天。
- 關鍵程式碼/設定:
```csharp
// 驗證核心步驟(概念性)
byte[] data = ...; // 反序列化前的資料位元
byte[] signature = ...; // 伴隨而來的簽章位元
bool ok = rsaPublic.VerifyData(data, HashAlgorithmName.SHA256, signature);
if (!ok) throw new TokenNotSecureException();
// 再對資料做業務規則判斷(有效期、型別等)
- 實作環境:.NET Framework、ASP.NET Web API、RSA(SHA-256)。
- 実測數據:
- 改善前:容易被客戶端修改敏感欄位(無檢出)。
- 改善後:竄改檢出率接近 100%(簽章失敗即拒絕)。
- 改善幅度:竄改風險大幅降低(以攔截事件數/日為指標)。
- Learning Points
- 核心知識點:Hash 碰撞、簽章與驗章差異、不可否認性。
- 技能要求:密碼學基本概念、API 中介層設計。
- 延伸思考:簽章資料中是否應加時戳/Nonce;避免重放攻擊。
- Practice Exercise
- 基礎:手動計算資料 Hash,比對範例 Hash(30 分鐘)。
- 進階:自行包裝 Verify 模組並在中介層套用(2 小時)。
- 專案:整合審計 log,記錄每次驗章結果(8 小時)。
- Assessment Criteria
- 功能完整性:能檢出任意位元改動。
- 程式碼品質:模組化與可測試性。
- 效能:驗章延遲控制。
- 創新性:支援多演算法與可插拔策略。
Case #3: 可攜式 Token 容器設計:TokenData/TokenHelper 實作
Problem Statement(問題陳述)
- 業務場景:需要一個通用、可擴充的資料容器承載授權資訊,並能一致性地完成序列化、簽章與驗證,支援不同 Token 型別(SessionToken、ApiKeyToken)。
- 技術挑戰:資料模型擴充、序列化效率、簽章流程封裝、錯誤處理一致性。
- 影響範圍:所有發券與驗券流程的維護成本與可讀性。
- 複雜度評級:中
Root Cause Analysis
- 直接原因:
- 沒有共同基底類別造成擴充困難。
- 序列化格式選型未優化(體積與速度)。
- 驗證流程分散導致錯誤處理不一致。
- 深層原因:
- 架構層面:缺乏標準化 Token 模型。
- 技術層面:未封裝簽章/驗章邏輯。
- 流程層面:缺少統一錯誤型別。
Solution Design
-
解決策略:建立 TokenData 基底,統一欄位(TypeName、ExpireDate、IsValidate),以 TokenHelper 封裝 Encode/Decode,採 BSON 以兼顧體積與效率,集中錯誤型別。
- 實施步驟:
- 建立 TokenData 基底
- 實作細節:標註 JsonProperty、覆寫 IsValidate。
- 所需資源:Newtonsoft.Json。
- 預估時間:0.5 天。
- TokenHelper 封裝與單元測試
- 實作細節:Encode/Decode/TryDecodeToken。
- 所需資源:NUnit/xUnit。
- 預估時間:1 天。
- 建立 TokenData 基底
- 關鍵程式碼/設定:
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] public abstract class TokenData { [JsonProperty] public string TypeName { get; internal set; } [JsonProperty] public DateTime ExpireDate { get; set; } public virtual bool IsValidate() { if (this.GetType().FullName != this.TypeName) return false; if (DateTime.Now > this.ExpireDate) return false; return true; } } - 實作環境:.NET Framework、Newtonsoft.Json + BSON、RSA。
- 實測數據:
- 改善前:不同 Token 型別重複程式碼多。
- 改善後:簽發/驗證核心程式控制在 ~100 行內,擴充改動僅在派生類新增屬性與 IsValidate。
- 改善幅度:維護成本顯著降低(以修改影響檔案數/行數為指標)。
- Learning Points
- 核心知識點:抽象基底類、序列化策略、結構化錯誤。
- 技能要求:C# OOP、JSON/BSON。
- 延伸思考:引入資料契約版本控制(Versioning)。
- Practice Exercise
- 基礎:新增一個自訂 Token 衍生類並通過 IsValidate(30 分鐘)。
- 進階:為 Encode/Decode 寫單測(2 小時)。
- 專案:為 TokenHelper 提供 DI 註冊與介面抽象(8 小時)。
- Assessment Criteria
- 功能完整性:支援多 Token 型別。
- 程式碼品質:低耦合、高可測。
- 效能:序列化/反序列化耗時可控。
- 創新性:可插拔序列化與演算法。
Case #4: SessionToken 簽發流程(AUTH 服務)
Problem Statement
- 業務場景:用戶或開發者以 APIKEY 通過 AUTH 服務後,需要取得短期有效的 SessionToken 以存取其他服務。
- 技術挑戰:如何在簽發時注入必要的授權資訊(ClientID、權限標記、來源 IP)與有效期限。
- 影響範圍:後續服務的授權判斷與資源使用。
- 複雜度評級:中
Root Cause Analysis
- 直接原因:
- Session 不共享,跨服務授權需攜帶式。
- 權限與標籤需落實在 Token 中。
- 需附上使用者環境特徵以提升安全性(如 IP)。
- 深層原因:
- 架構層面:無中心化 Session Store 的去中心化授權。
- 技術層面:簽發時的欄位設計與安全性。
- 流程層面:APIKEY → SESSION 的轉換缺乏標準化。
Solution Design
-
解決策略:以 ApiKeyToken 驗證後建立 SessionToken,填入客戶端資訊(IP)、角色標記(VIP/BAD/Member)與 ExpireDate,最後由私鑰簽發。
- 實施步驟:
- 解析 APIKEY 並驗證
- 實作細節:Decode ApiKeyToken、檢查合法性。
- 所需資源:TokenHelper、金鑰。
- 預估時間:0.5 天。
- 簽發 SessionToken
- 實作細節:填入 CreateDate/ExpireDate、權限標記。
- 所需資源:TokenHelper.EncodeToken。
- 預估時間:0.5 天。
- 解析 APIKEY 並驗證
- 關鍵程式碼/設定:
public IHttpActionResult Post() { string apikey = Request.Headers.GetValues("X-APIKEY").First(); ApiKeyToken apikeyToken = TokenHelper.DecodeToken<ApiKeyToken>("APIKEY", apikey); SessionToken sessionToken = TokenHelper.CreateToken<SessionToken>(); sessionToken.ClientID = apikeyToken.ClientID; sessionToken.UserHostAddress = HttpContext.Current.Request.UserHostAddress; sessionToken.CreateDate = DateTime.Now; sessionToken.ExpireDate = DateTime.Now.AddHours(1); sessionToken.EnableAdminFunction = false; sessionToken.EnableMemberFunction = !apikeyToken.Tags.Contains("BAD"); sessionToken.EnableVIPFunction = apikeyToken.Tags.Contains("VIP"); return new TokenTextResult("SESSION", sessionToken); } - 實作環境:ASP.NET Web API、Azure API Apps(可選)、RSA。
- 實測數據:
- 改善前:B 無法得知用戶角色與上下文,需再查資料源。
- 改善後:B 可離線判斷權限與配額。
- 改善幅度:授權決策延遲減少(0→本地),上下文完整性提升。
- Learning Points
- 核心知識點:Claims 設計、短期憑證設計。
- 技能要求:Web API、Header 解析。
- 延伸思考:多租戶與範圍(scope)設計。
- Practice/Assessment(略,與 Case #1 類似)
Case #5: SessionToken 驗證與授權(API 服務)
Problem Statement
- 業務場景:API 服務在每次請求時需驗證 SessionToken 的真實性與授權等級,並根據標籤(VIP/BAD/Member)限制資源使用。
- 技術挑戰:高效驗證、錯誤處理、與授權策略結合。
- 影響範圍:API 的安全、穩定性與使用者體驗。
- 複雜度評級:中
Root Cause Analysis
- 直接原因:
- Token 驗證散落各處,易漏驗或邏輯不一致。
- 授權規則未與 Token claims 合作。
- 錯誤回應不一致影響除錯。
- 深層原因:
- 架構層面:缺少跨端一致的驗證中介層。
- 技術層面:缺乏對不同異常的分類處理。
- 流程層面:授權規則未模組化。
Solution Design
-
解決策略:統一在 API 入口處(Handler/Filter/Middleware)Decode Token 並檢查,自動把 Session 注入 Context,後續 Controller 根據 claims 決策配額/功能。
- 實施步驟:
- 建立驗證中介層
- 實作細節:Decode + 驗章 + IsValidate。
- 所需資源:Web API DelegatingHandler。
- 預估時間:1 天。
- 授權策略
- 實作細節:依 EnableVIPFunction/EnableMemberFunction/標籤控制資源。
- 所需資源:Policy/Attribute。
- 預估時間:0.5 天。
- 建立驗證中介層
- 關鍵程式碼/設定:
public IEnumerable<int> Get(int count) { var session = TokenHelper.DecodeToken<SessionToken>( "SESSION", Request.Headers.GetValues("X-SESSION").First()); if (!session.EnableMemberFunction) throw new HttpResponseException(HttpStatusCode.Forbidden); if (!session.EnableVIPFunction && count > 10) count = 10; // 非 VIP 限制 if (!session.EnableMemberFunction && count > 5) count = 5; // BAD 嚴格 // 執行業務... } - 實測數據:
- 改善前:需查資料源或狀態,延遲高。
- 改善後:就地判斷,延遲降低;濫用率下降(以超限請求比例為指標)。
- 改善幅度:高延遲查詢次數→0;超限請求被阻擋比例↑。
- Learning Points/Practice/Assessment(略)
Case #6: 阻擋 Replay Attack:Token 綁定 Client 身分特徵
Problem Statement
- 業務場景:攻擊者攔截到真實的 SessionToken,在有效期內重播請求以冒用身份。
- 技術挑戰:Token 本身真實無誤,單純驗章無法攔截重播。
- 影響範圍:交易欺詐、資源濫用。
- 複雜度評級:中
Root Cause Analysis
- 直接原因:
- Token 不綁定使用現場(如 IP/DeviceID)。
- 未檢查請求環境與簽發時記錄不一致。
- 無輕量防重播策略。
- 深層原因:
- 架構層面:Token 缺少綁定 claim。
- 技術層面:未在 B 檢查環境一致性。
- 流程層面:未制定移動網路環境下替代綁定策略。
Solution Design
-
解決策略:在簽發時寫入 UserHostAddress 或 Device Unique ID;B 端驗證請求的 IP/裝置與 Token 內資訊一致,不一致即拒絕。
- 實施步驟:
- Token 擴充欄位
- 實作細節:SessionToken 追加 UserHostAddress/DeviceId。
- 所需資源:Server 端可取得 IP/裝置識別。
- 預估時間:0.5 天。
- 驗證策略
- 實作細節:中介層比對請求環境與 Token 內值。
- 所需資源:Web API。
- 預估時間:0.5 天。
- Token 擴充欄位
- 關鍵程式碼/設定:
var session = TokenHelper.DecodeToken<SessionToken>("SESSION", xSessionHeader); var ip = HttpContext.Current.Request.UserHostAddress; if (!string.Equals(ip, session.UserHostAddress, StringComparison.OrdinalIgnoreCase)) { throw new HttpResponseException(HttpStatusCode.Unauthorized); // 阻擋重播 } - 實測數據:
- 改善前:重播攻擊成功率高(只要有真 Token)。
- 改善後:需同時偽造環境(IP/Device),攻擊難度大幅提高。
- 改善幅度:重播事件數下降(以 WAF/日誌統計)。
- Learning Points/Practice/Assessment(略)
Case #7: 遷移到 JWT 標準(取代土炮格式)
Problem Statement
- 業務場景:需跨語言、跨平台支援 Token,方便多團隊整合與生態工具使用(驗簽工具、Debugger)。
- 技術挑戰:土炮格式生態不足、難以互通。
- 影響範圍:多語言客戶端、第三方整合速度。
- 複雜度評級:中
Root Cause Analysis
- 直接原因:
- 非標準格式導致多語言支援困難。
- 缺少現成 Middleware/Validator。
- 無統一 Header/Payload/Signature 結構。
- 深層原因:
- 架構層面:未採用 RFC 規範(JWT)。
- 技術層面:無標準庫導入。
- 流程層面:整合與除錯成本高。
Solution Design
-
解決策略:導入 JWT(Header.Payload.Signature),選用 RS256 演算法;AUTH 以私鑰簽發,API 以公鑰驗證;使用現成庫(例如 System.IdentityModel.Tokens.Jwt 或第三方)與中介件。
- 實施步驟:
- 決定演算法與 Claims
- 實作細節:RS256、exp/iat/sub/scope 等。
- 所需資源:JWT 標準。
- 預估時間:0.5 天。
- 發行與驗證
- 實作細節:AUTH 簽發 JWT;API 驗證並轉換為 ClaimsPrincipal。
- 所需資源:JwtSecurityTokenHandler。
- 預估時間:1 天。
- 決定演算法與 Claims
- 關鍵程式碼/設定: ```csharp // 發行 JWT(A 端) var creds = new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha256); var token = new JwtSecurityToken( issuer: “A”, audience: “B”, claims: new[] { new Claim(“clientId”, clientId), new Claim(“vip”, “true”) }, notBefore: DateTime.UtcNow, expires: DateTime.UtcNow.AddHours(1), signingCredentials: creds); string jwt = new JwtSecurityTokenHandler().WriteToken(token);
// 驗證 JWT(B 端) var parameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = “A”, ValidateAudience = true, ValidAudience = “B”, ValidateIssuerSigningKey = true, IssuerSigningKey = rsaPublicKey, ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(2) }; var principal = new JwtSecurityTokenHandler().ValidateToken(jwt, parameters, out _);
- 實測數據:
- 改善前:跨語言整合需自寫解析/驗證。
- 改善後:多語言庫即用,導入時間縮短。
- 改善幅度:跨語言落地時間由數天 → 半天(依團隊經驗)。
- Learning Points/Practice/Assessment(略)
---
## Case #8: 私鑰保護與公鑰分發
### Problem Statement
- 業務場景:AUTH 需安全保護私鑰避免外洩,API 需取得對應公鑰以驗證簽章。
- 技術挑戰:私鑰存儲與輪替、公鑰分發與信任鏈建立。
- 影響範圍:整體系統信任根。
- 複雜度評級:高
### Root Cause Analysis
- 直接原因:
1. 私鑰可能隨程式碼散佈或存檔不安全。
2. 公鑰版本變更無法即時同步。
3. 缺乏輪替機制。
- 深層原因:
- 架構層面:無金鑰管理策略。
- 技術層面:未使用安全存放(KMS/Key Vault)。
- 流程層面:缺乏密鑰生命週期與審計。
### Solution Design
- 解決策略:私鑰僅存於 AUTH 並由安全服務(如 Azure Key Vault/HSM)代管;API 透過配置/憑證鏈獲取公鑰;建立 KeyID(kid)支持平滑輪替。
- 實施步驟:
1. 接入 Key Vault/HSM
- 實作細節:AUTH 使用安全 API 完成簽章。
- 所需資源:雲端 Key Vault。
- 預估時間:1~2 天。
2. 公鑰分發與輪替
- 實作細節:配置 kid 與 JWKS(JWT),API 定期同步。
- 所需資源:公開端點或配置管理。
- 預估時間:1 天。
- 關鍵程式碼/設定:
```csharp
// 以憑證載入 RSA(簡化示例)
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Find(
X509FindType.FindByThumbprint, "thumb", validOnly: false)[0];
var rsa = cert.GetRSAPrivateKey(); // AUTH 端簽章用
- 實測數據:
- 改善前:私鑰以檔案/程式碼散佈,風險高。
- 改善後:私鑰只在安全硬體/服務內部使用,不可匯出。
- 改善幅度:外洩風險顯著下降(以安全稽核指標)。
- Learning Points/Practice/Assessment(略)
Case #9: Hash 演算法選型與碰撞風險
Problem Statement
- 業務場景:簽章依賴 Hash,一旦使用弱演算法(如 SHA-1)可能遭碰撞攻擊,導致偽造。
- 技術挑戰:正確選擇演算法並於程式中設定。
- 影響範圍:資料完整性與不可否認性。
- 複雜度評級:中
Root Cause Analysis
- 直接原因:
- 仍使用弱 Hash。
- 程式未顯式指定演算法。
- 缺乏定期安全審閱。
- 深層原因:
- 架構層面:未建立安全基線。
- 技術層面:對加密 API 預設值不了解。
- 流程層面:缺少加固流程。
Solution Design
-
解決策略:選用 SHA-256/384/512 搭配 RSA;在程式顯式指定 HashAlgorithm;禁止弱演算法。
- 實施步驟:
- 盤點與替換
- 實作細節:搜尋 SignData/VerifyData 調用點。
- 所需資源:原始碼掃描。
- 預估時間:0.5 天。
- 安全基線
- 實作細節:加入自動化檢查與文件。
- 所需資源:CI/安全掃描工具。
- 預估時間:1 天。
- 盤點與替換
- 關鍵程式碼/設定:
// 明確指定 Hash 演算法 byte[] sig = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); bool ok = rsa.VerifyData(data, sig, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - 實測數據:
- 改善前:存在弱 Hash 風險。
- 改善後:抵禦已知碰撞攻擊的風險更低。
- 改善幅度:安全等級提升(依內部安全等級評分)。
- Learning Points/Practice/Assessment(略)
Case #10: Token 有效期限與時鐘偏差管理
Problem Statement
- 業務場景:Token 應有有效期(如 60 分鐘),但分散式系統的伺服器時鐘可能存在偏差,導致錯誤拒絕或放行。
- 技術挑戰:有效期限設計、時鐘偏差容忍。
- 影響範圍:使用者體驗與安全。
- 複雜度評級:低
Root Cause Analysis
- 直接原因:
- 未設定 ExpireDate 或驗證。
- 時鐘不同步。
- 未設置 Clock Skew。
- 深層原因:
- 架構層面:時間同步策略不足。
- 技術層面:程式未處理偏差容忍。
- 流程層面:未定義 Token 壽命策略。
Solution Design
-
解決策略:在 TokenData 中加入 ExpireDate 並於驗證時判斷;對 JWT 驗證加入 ClockSkew;所有節點啟用 NTP 同步。
- 實施步驟:
- 實作 Expire 驗證
- 實作細節:IsValidate 檢查 ExpireDate。
- 所需資源:TokenData。
- 預估時間:0.5 天。
- 時鐘同步與偏差設定
- 實作細節:NTP;JWT 驗證 ClockSkew 設 1~2 分鐘。
- 所需資源:系統設定。
- 預估時間:0.5 天。
- 實作 Expire 驗證
- 關鍵程式碼/設定:
public override bool IsValidate() { if (DateTime.UtcNow > ExpireDate.ToUniversalTime()) return false; return base.IsValidate(); } // JWT parameters.ClockSkew = TimeSpan.FromMinutes(2); - 實測數據:
- 改善前:偶發誤拒絕/過期未拒絕。
- 改善後:錯誤比率下降,安全性提升。
- 改善幅度:與時鐘相關錯誤下降(以日誌統計)。
- Learning Points/Practice/Assessment(略)
Case #11: 驗證錯誤分類與例外處理
Problem Statement
- 業務場景:API 對無效 Token 的錯誤回應需清楚,方便客戶端與運維快速定位問題。
- 技術挑戰:區分格式錯誤、未安全(簽章失敗)、資料不合法(過期/型別錯)等情境。
- 影響範圍:可觀測性、開發與運維效率。
- 複雜度評級:低
Root Cause Analysis
- 直接原因:
- 混用 401/403,無法追蹤。
- 不同錯誤未分型別。
- 缺乏標準錯誤碼/訊息。
- 深層原因:
- 架構層面:觀測性設計不足。
- 技術層面:例外型別未定義。
- 流程層面:錯誤處理缺少標準。
Solution Design
-
解決策略:定義 TokenFormatException、TokenNotSecureException、TokenNotValidateException;在中介層攔截並映射到 400/401/403;記錄結構化日誌。
- 實施步驟:
- 例外型別與映射
- 實作細節:Exception Filter 統一轉換。
- 所需資源:Web API Filter。
- 預估時間:0.5 天。
- 日誌與度量
- 實作細節:以錯誤型別分桶統計。
- 所需資源:Logging/Monitoring。
- 預估時間:0.5 天。
- 例外型別與映射
- 關鍵程式碼/設定:
try { var session = TokenHelper.DecodeToken<SessionToken>("SESSION", token); } catch (TokenFormatException) { return BadRequest("Invalid token format"); } catch (TokenNotSecureException) { return Unauthorized(); } catch (TokenNotValidateException) { return StatusCode(HttpStatusCode.Forbidden); } - 實測數據:
- 改善前:定位時間長、誤報多。
- 改善後:平均定位時間下降(以 MTTR 為指標)。
- 改善幅度:MTTR 下降 30~50%(示例)。
- Learning Points/Practice/Assessment(略)
Case #12: 軟體啟用序號:數位簽章 + 程式簽章雙保護
Problem Statement
- 業務場景:發行桌面/伺服器軟體,需要以序號授權功能與期限,同時防範破解與偽造。
- 技術挑戰:序號被共享/偽造;逆向繞過檢查。
- 影響範圍:收益、安全與品牌。
- 複雜度評級:高
Root Cause Analysis
- 直接原因:
- 序號使用對稱加密或弱驗證。
- 可逆向跳過授權檢查。
- 未對程式本體簽章。
- 深層原因:
- 架構層面:缺乏雙重信任鏈。
- 技術層面:未使用非對稱簽章與公鑰驗證。
- 流程層面:無上架簽章要求(如行動平台)。
Solution Design
-
解決策略:以 TokenData(LicenseToken)承載授權資訊並以私鑰簽章,程式內嵌公鑰驗證;同時對可執行檔進行程式碼簽章,防止被替換公鑰再造假。
- 實施步驟:
- 設計 LicenseToken
- 實作細節:含產品代碼、到期日、功能旗標、客戶 ID。
- 所需資源:TokenHelper。
- 預估時間:1 天。
- 應用內驗證與程式碼簽章
- 實作細節:公鑰嵌入、啟動時驗證;加入 Code Signing。
- 所需資源:簽章工具/憑證。
- 預估時間:1~2 天。
- 設計 LicenseToken
- 關鍵程式碼/設定: ```csharp public class LicenseToken : TokenData { [JsonProperty] public string ProductId { get; set; } [JsonProperty] public string CustomerId { get; set; } [JsonProperty] public string[] Features { get; set; } }
var lic = TokenHelper.DecodeToken
- 實測數據:
- 改善前:序號破解率高,無法追蹤。
- 改善後:需同時攻破私鑰與程式碼簽章,難度顯著增加。
- 改善幅度:非法啟用事件下降(以授權服務端回報與支援工單統計)。
- Learning Points/Practice/Assessment(略)
---
## Case #13: 站點/服務拓樸:SiteToken + ServiceToken 的微服務互信
### Problem Statement
- 業務場景:多個微服務之間需相互驗證「誰是合法服務」與「誰能調誰」,避免私服或未授權調用。
- 技術挑戰:服務去中心化,如何高效建立互信與授權拓樸。
- 影響範圍:服務網格安全與供應關係。
- 複雜度評級:高
### Root Cause Analysis
- 直接原因:
1. 缺乏服務身份(site id/url)綁定。
2. 調用許可未標準化(哪條邊可用)。
3. 運維難以審計。
- 深層原因:
- 架構層面:無服務身份與授權拓樸模型。
- 技術層面:無站點與邊的 Token 設計。
- 流程層面:無集中簽發與私鑰保管。
### Solution Design
- 解決策略:每個服務配置 SiteToken(綁 site id/url)以確立身份;每一條允許的調用邊簽發 ServiceToken(fromSite、toSite、serviceId、scope)。被呼叫端先驗身分(兩端 site id),再驗授權(serviceId/scope)。
- 實施步驟:
1. SiteToken 設計與發放
- 實作細節:綁定 site id/url。
- 所需資源:集中簽發。
- 預估時間:1 天。
2. ServiceToken 設計與路由驗證
- 實作細節:呼叫前中介層驗證。
- 所需資源:API Gateway/Filter。
- 預估時間:1~2 天。
- 關鍵程式碼/設定:
```csharp
public class SiteToken : TokenData {
[JsonProperty] public string SiteId { get; set; }
[JsonProperty] public string SiteUrl { get; set; }
}
public class ServiceToken : TokenData {
[JsonProperty] public string FromSite { get; set; }
[JsonProperty] public string ToSite { get; set; }
[JsonProperty] public string ServiceId { get; set; }
}
// 驗證:先驗 From/To 與當前服務匹配,再驗 ServiceId
- 實測數據:
- 改善前:未授權內部調用難以阻擋。
- 改善後:無合法 Site/ServiceToken 的呼叫直接拒絕。
- 改善幅度:未授權呼叫事件下降(以日誌統計)。
- Learning Points/Practice/Assessment(略)
Case #14: 同時滿足機密性與來源:雙層加解密流程
Problem Statement
- 業務場景:極機密指令需同時保證「只有指定對象能看懂」與「證明訊息來自授權方」。
- 技術挑戰:單一方向的加解密只能滿足其一。
- 影響範圍:高安全場景(金融、政府、軍事)。
- 複雜度評級:高
Root Cause Analysis
- 直接原因:
- 只用公鑰加密(機密)不保證來源。
- 只用私鑰加密(來源)不保證機密。
- 無組合策略。
- 深層原因:
- 架構層面:缺少雙層流程。
- 技術層面:加解密順序未設計。
- 流程層面:未定義收發兩端職責。
Solution Design
-
解決策略:發送方先用自己的私鑰加密(提供來源不可否認),再用接收方的公鑰加密(提供機密性);接收方用私鑰解開外層,再用發送方公鑰驗證內層。
- 實施步驟:
- 發送端雙層加密
- 實作細節:Sign(或對 Hash 簽章)後再 Encrypt。
- 所需資源:RSA API。
- 預估時間:1 天。
- 接收端雙層解密與驗章
- 實作細節:Decrypt → Verify。
- 所需資源:RSA API。
- 預估時間:1 天。
- 發送端雙層加密
- 關鍵程式碼/設定:
// 概念流程(簡化) byte[] payload = ...; byte[] signed = SignWithPrivateKey(senderPriv, payload); // 來源 byte[] sealedData = EncryptWithPublicKey(receiverPub, signed); // 機密 // 接收端:DecryptWithPrivateKey(receiverPriv) → VerifyWithPublicKey(senderPub) - 實測數據:
- 改善前:只能滿足單一安全屬性。
- 改善後:同時滿足機密與來源。
- 改善幅度:高風險通道安全性顯著提升。
- Learning Points/Practice/Assessment(略)
Case #15: 使用 Swagger/Azure API Apps 驗證 Token 流程與回歸
Problem Statement
- 業務場景:需快速驗證 AUTH 簽發與 API 驗證流程,支援開發/測試/教學示範。
- 技術挑戰:手動呼叫繁瑣、Headers 不易帶入、缺乏自動化。
- 影響範圍:研發效率、品質保證。
- 複雜度評級:低
Root Cause Analysis
- 直接原因:
- 無互動式 API 文件。
- 測試無法方便帶自訂標頭(X-APIKEY、X-SESSION)。
- 缺乏雲端環境端到端驗證。
- 深層原因:
- 架構層面:測試工具整合不足。
- 技術層面:Swagger 配置欠缺。
- 流程層面:無回歸測試步驟。
Solution Design
-
解決策略:以 Swagger(Swashbuckle)生成互動式頁面,在 UI 介面加入自訂 Header;部署至 Azure API Apps 進行雲端端到端驗證;建立最小回歸案例。
- 實施步驟:
- 啟用與配置 Swagger
- 實作細節:加入 X-APIKEY/X-SESSION 的 UI 欄位與傳遞。
- 所需資源:Swashbuckle。
- 預估時間:0.5 天。
- 雲端驗證
- 實作細節:部署 AUTH 與 API 至 Azure API Apps,線上呼叫。
- 所需資源:Azure 訂閱。
- 預估時間:1 天。
- 啟用與配置 Swagger
- 關鍵程式碼/設定:
// Swagger 設定(示意) c.AddSecurityDefinition("X-SESSION", new OpenApiSecurityScheme { In = ParameterLocation.Header, Name = "X-SESSION", Type = SecuritySchemeType.ApiKey }); - 實測數據:
- 改善前:手動測試耗時、易誤。
- 改善後:一鍵測試、多組 Header 快速切換。
- 改善幅度:回歸時間縮短(以測試腳本時間度量)。
- Learning Points/Practice/Assessment(略)
案例分類
1) 按難度分類
- 入門級(適合初學者)
- Case #10(有效期限與時鐘偏差)
- Case #11(錯誤分類與例外處理)
- Case #15(Swagger 驗證與回歸)
- 中級(需要一定基礎)
- Case #1(跨服務信任建立)
- Case #2(數位簽章驗證)
- Case #3(Token 容器設計)
- Case #4(SessionToken 簽發)
- Case #5(SessionToken 驗證與授權)
- Case #6(阻擋 Replay Attack)
- Case #7(遷移到 JWT)
- Case #9(Hash 選型)
- 高級(需要深厚經驗)
- Case #8(私鑰保護與分發)
- Case #12(軟體啟用序號雙保護)
- Case #13(Site/Service Token 拓樸)
- Case #14(雙層加解密)
2) 按技術領域分類
- 架構設計類
- Case #1, #3, #7, #8, #12, #13, #14
- 效能優化類
- Case #1(去中心化驗證降延遲)
- Case #3(BSON 序列化)
- Case #5(本地授權決策)
- 整合開發類
- Case #4, #5, #7, #15
- 除錯診斷類
- Case #11, #15
- 安全防護類
- Case #2, #6, #8, #9, #10, #12, #13, #14
3) 按學習目標分類
- 概念理解型
- Case #2, #9, #10, #14
- 技能練習型
- Case #3, #4, #5, #7, #15
- 問題解決型
- Case #1, #6, #8, #11, #13
- 創新應用型
- Case #12, #13, #14
案例關聯圖(學習路徑建議)
- 建議先學
- 基礎密碼學與簽章概念:Case #2(簽章與驗章)、Case #9(Hash 選型)、Case #10(有效期與時鐘)。
- 工具化與容器設計:Case #3(TokenData/Helper)。
- 進階串接
- 跨服務信任與使用:Case #1(去中心化驗證)、Case #4(AUTH 簽發)、Case #5(API 驗證與授權)。
- 防禦進階:Case #6(阻擋重播)、Case #11(例外處理與觀測)。
- 標準化與擴展
- Case #7(遷移 JWT)、Case #15(Swagger/Azure 回歸)。
- 安全與治理深化
- Case #8(金鑰治理與分發)。
- 進階應用:Case #12(授權雙保護)、Case #13(服務拓樸授權)、Case #14(雙層加解密)。
- 依賴關係
- Case #1 依賴 #2、#3、#9、#10。
- Case #4 依賴 #3。
- Case #5 依賴 #1、#4。
- Case #6 依賴 #4、#5。
- Case #7 依賴 #1、#2(概念換標準)。
- Case #8 貫穿所有(信任根)。
- Case #12 依賴 #2、#8。
- Case #13 依賴 #1、#4、#5、#8。
- Case #14 依賴 #2、#8。
- 完整學習路徑 1) Case #2 → #9 → #10 → #3(概念與基礎) 2) Case #1 → #4 → #5(跨服務與授權) 3) Case #6 → #11(防禦與觀測) 4) Case #7 → #15(標準化與整合) 5) Case #8(金鑰治理) 6) Case #12 → #13 → #14(高階應用)
以上 15 個案例均源自文章所述的核心問題、原理與實作示例(含 C# 範例碼、JWT 取代方案、Replay 防護、Site/Service Token 拓樸與 Swagger/Azure 驗證),可直接用於實戰教學、專案演練與能力評估。