微服務架構 #4, 如何強化微服務的安全性? API Token / JWT 的應用

以下為基於文章內容所萃取並結構化的 15 個教學型解決方案案例。每個案例均包含問題、根因、完整解法(含程式碼/流程)、效益與練習評估,適合用於實戰教學與專案演練。

Case #1: 跨服務信任建立:以 RSA 簽章的 API Token

Problem Statement(問題陳述)

  • 業務場景:在微服務/服務導向場景中,使用者於 A 服務完成付費或驗證後,需要前往 B 服務消費或使用 API,但 A 與 B 不具備即時、安全的互通管道(跨網域、跨組織、不同運維團隊)。需要一種在不直接呼叫 A 的情況下,讓 B 能信任使用者資訊與權限的機制。
  • 技術挑戰:如何確保資料未被竄改且來源可信?如何避免每次驗證都回呼 A 而造成高延遲與單點瓶頸?
  • 影響範圍:所有跨服務的授權與交易流程、API 安全、營運成本與使用者體驗。
  • 複雜度評級:中

Root Cause Analysis(根因分析)

  • 直接原因:
    1. 缺乏跨服務的信任傳遞機制,B 無法確認 A 所簽發的資訊真偽。
    2. 網路不安全(公開網際網路),傳輸資料可能遭竊聽或竄改。
    3. 實時調 A 驗證增加耦合與延遲。
  • 深層原因:
    • 架構層面:缺少去中心化信任設計,依賴同步授權查詢。
    • 技術層面:未使用非對稱密碼學(RSA)與數位簽章來保證完整性與來源。
    • 流程層面:授權資訊未標準化為可攜帶的安全票據(Token)。

Solution Design(解決方案設計)

  • 解決策略:在 A 使用私鑰對授權資料簽章,B 保存 A 的公鑰,對來自客戶端攜帶的 Token 進行驗證(VerifyData)。驗證成功即可離線信任內容,避免回呼 A,達成去中心化、低耦合的跨服務信任。

  • 實施步驟:
    1. 產生與管理金鑰
      • 實作細節:A 保存 RSA Private Key;B 保存對應 Public Key。
      • 所需資源:RSACryptoServiceProvider/RSACng、憑證或金鑰管理。
      • 預估時間:0.5 天。
    2. 設計 Token 資料結構
      • 實作細節:以 TokenData(含 ExpireDate、TypeName 等)表示可攜授權資料。
      • 所需資源:C#、Newtonsoft.Json/BSON。
      • 預估時間:0.5 天。
    3. 在 A 簽發 Token
      • 實作細節:序列化資料、SignData 後打包(data + signature)。
      • 所需資源:TokenHelper.EncodeToken。
      • 預估時間:0.5 天。
    4. 在 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(string keyName, string tokenText) where T : TokenData, new() { var parts = tokenText.Split('.'); var data = Convert.FromBase64String(parts[0]); var sig = Convert.FromBase64String(parts[1]); // 來源/完整性驗證 bool secure = _RSACSP_STORE[keyName].VerifyData(data, _HALG, sig); if (!secure) throw new TokenNotSecureException(); // 反序列化 + 資料規則驗證 T t = DeserializeBson(data); if (!t.IsValidate()) throw new TokenNotValidateException(); return t; }


- 實際案例:文章中的 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

  • 直接原因:
    1. 沒有共同基底類別造成擴充困難。
    2. 序列化格式選型未優化(體積與速度)。
    3. 驗證流程分散導致錯誤處理不一致。
  • 深層原因:
    • 架構層面:缺乏標準化 Token 模型。
    • 技術層面:未封裝簽章/驗章邏輯。
    • 流程層面:缺少統一錯誤型別。

Solution Design

  • 解決策略:建立 TokenData 基底,統一欄位(TypeName、ExpireDate、IsValidate),以 TokenHelper 封裝 Encode/Decode,採 BSON 以兼顧體積與效率,集中錯誤型別。

  • 實施步驟:
    1. 建立 TokenData 基底
      • 實作細節:標註 JsonProperty、覆寫 IsValidate。
      • 所需資源:Newtonsoft.Json。
      • 預估時間:0.5 天。
    2. TokenHelper 封裝與單元測試
      • 實作細節:Encode/Decode/TryDecodeToken。
      • 所需資源:NUnit/xUnit。
      • 預估時間:1 天。
  • 關鍵程式碼/設定:
    [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

  • 直接原因:
    1. Session 不共享,跨服務授權需攜帶式。
    2. 權限與標籤需落實在 Token 中。
    3. 需附上使用者環境特徵以提升安全性(如 IP)。
  • 深層原因:
    • 架構層面:無中心化 Session Store 的去中心化授權。
    • 技術層面:簽發時的欄位設計與安全性。
    • 流程層面:APIKEY → SESSION 的轉換缺乏標準化。

Solution Design

  • 解決策略:以 ApiKeyToken 驗證後建立 SessionToken,填入客戶端資訊(IP)、角色標記(VIP/BAD/Member)與 ExpireDate,最後由私鑰簽發。

  • 實施步驟:
    1. 解析 APIKEY 並驗證
      • 實作細節:Decode ApiKeyToken、檢查合法性。
      • 所需資源:TokenHelper、金鑰。
      • 預估時間:0.5 天。
    2. 簽發 SessionToken
      • 實作細節:填入 CreateDate/ExpireDate、權限標記。
      • 所需資源:TokenHelper.EncodeToken。
      • 預估時間:0.5 天。
  • 關鍵程式碼/設定:
    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

  • 直接原因:
    1. Token 驗證散落各處,易漏驗或邏輯不一致。
    2. 授權規則未與 Token claims 合作。
    3. 錯誤回應不一致影響除錯。
  • 深層原因:
    • 架構層面:缺少跨端一致的驗證中介層。
    • 技術層面:缺乏對不同異常的分類處理。
    • 流程層面:授權規則未模組化。

Solution Design

  • 解決策略:統一在 API 入口處(Handler/Filter/Middleware)Decode Token 並檢查,自動把 Session 注入 Context,後續 Controller 根據 claims 決策配額/功能。

  • 實施步驟:
    1. 建立驗證中介層
      • 實作細節:Decode + 驗章 + IsValidate。
      • 所需資源:Web API DelegatingHandler。
      • 預估時間:1 天。
    2. 授權策略
      • 實作細節:依 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

  • 直接原因:
    1. Token 不綁定使用現場(如 IP/DeviceID)。
    2. 未檢查請求環境與簽發時記錄不一致。
    3. 無輕量防重播策略。
  • 深層原因:
    • 架構層面:Token 缺少綁定 claim。
    • 技術層面:未在 B 檢查環境一致性。
    • 流程層面:未制定移動網路環境下替代綁定策略。

Solution Design

  • 解決策略:在簽發時寫入 UserHostAddress 或 Device Unique ID;B 端驗證請求的 IP/裝置與 Token 內資訊一致,不一致即拒絕。

  • 實施步驟:
    1. Token 擴充欄位
      • 實作細節:SessionToken 追加 UserHostAddress/DeviceId。
      • 所需資源:Server 端可取得 IP/裝置識別。
      • 預估時間:0.5 天。
    2. 驗證策略
      • 實作細節:中介層比對請求環境與 Token 內值。
      • 所需資源:Web API。
      • 預估時間:0.5 天。
  • 關鍵程式碼/設定:
    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

  • 直接原因:
    1. 非標準格式導致多語言支援困難。
    2. 缺少現成 Middleware/Validator。
    3. 無統一 Header/Payload/Signature 結構。
  • 深層原因:
    • 架構層面:未採用 RFC 規範(JWT)。
    • 技術層面:無標準庫導入。
    • 流程層面:整合與除錯成本高。

Solution Design

  • 解決策略:導入 JWT(Header.Payload.Signature),選用 RS256 演算法;AUTH 以私鑰簽發,API 以公鑰驗證;使用現成庫(例如 System.IdentityModel.Tokens.Jwt 或第三方)與中介件。

  • 實施步驟:
    1. 決定演算法與 Claims
      • 實作細節:RS256、exp/iat/sub/scope 等。
      • 所需資源:JWT 標準。
      • 預估時間:0.5 天。
    2. 發行與驗證
      • 實作細節:AUTH 簽發 JWT;API 驗證並轉換為 ClaimsPrincipal。
      • 所需資源:JwtSecurityTokenHandler。
      • 預估時間:1 天。
  • 關鍵程式碼/設定: ```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

  • 直接原因:
    1. 仍使用弱 Hash。
    2. 程式未顯式指定演算法。
    3. 缺乏定期安全審閱。
  • 深層原因:
    • 架構層面:未建立安全基線。
    • 技術層面:對加密 API 預設值不了解。
    • 流程層面:缺少加固流程。

Solution Design

  • 解決策略:選用 SHA-256/384/512 搭配 RSA;在程式顯式指定 HashAlgorithm;禁止弱演算法。

  • 實施步驟:
    1. 盤點與替換
      • 實作細節:搜尋 SignData/VerifyData 調用點。
      • 所需資源:原始碼掃描。
      • 預估時間:0.5 天。
    2. 安全基線
      • 實作細節:加入自動化檢查與文件。
      • 所需資源: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

  • 直接原因:
    1. 未設定 ExpireDate 或驗證。
    2. 時鐘不同步。
    3. 未設置 Clock Skew。
  • 深層原因:
    • 架構層面:時間同步策略不足。
    • 技術層面:程式未處理偏差容忍。
    • 流程層面:未定義 Token 壽命策略。

Solution Design

  • 解決策略:在 TokenData 中加入 ExpireDate 並於驗證時判斷;對 JWT 驗證加入 ClockSkew;所有節點啟用 NTP 同步。

  • 實施步驟:
    1. 實作 Expire 驗證
      • 實作細節:IsValidate 檢查 ExpireDate。
      • 所需資源:TokenData。
      • 預估時間:0.5 天。
    2. 時鐘同步與偏差設定
      • 實作細節:NTP;JWT 驗證 ClockSkew 設 1~2 分鐘。
      • 所需資源:系統設定。
      • 預估時間:0.5 天。
  • 關鍵程式碼/設定:
    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

  • 直接原因:
    1. 混用 401/403,無法追蹤。
    2. 不同錯誤未分型別。
    3. 缺乏標準錯誤碼/訊息。
  • 深層原因:
    • 架構層面:觀測性設計不足。
    • 技術層面:例外型別未定義。
    • 流程層面:錯誤處理缺少標準。

Solution Design

  • 解決策略:定義 TokenFormatException、TokenNotSecureException、TokenNotValidateException;在中介層攔截並映射到 400/401/403;記錄結構化日誌。

  • 實施步驟:
    1. 例外型別與映射
      • 實作細節:Exception Filter 統一轉換。
      • 所需資源:Web API Filter。
      • 預估時間:0.5 天。
    2. 日誌與度量
      • 實作細節:以錯誤型別分桶統計。
      • 所需資源: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

  • 直接原因:
    1. 序號使用對稱加密或弱驗證。
    2. 可逆向跳過授權檢查。
    3. 未對程式本體簽章。
  • 深層原因:
    • 架構層面:缺乏雙重信任鏈。
    • 技術層面:未使用非對稱簽章與公鑰驗證。
    • 流程層面:無上架簽章要求(如行動平台)。

Solution Design

  • 解決策略:以 TokenData(LicenseToken)承載授權資訊並以私鑰簽章,程式內嵌公鑰驗證;同時對可執行檔進行程式碼簽章,防止被替換公鑰再造假。

  • 實施步驟:
    1. 設計 LicenseToken
      • 實作細節:含產品代碼、到期日、功能旗標、客戶 ID。
      • 所需資源:TokenHelper。
      • 預估時間:1 天。
    2. 應用內驗證與程式碼簽章
      • 實作細節:公鑰嵌入、啟動時驗證;加入 Code Signing。
      • 所需資源:簽章工具/憑證。
      • 預估時間:1~2 天。
  • 關鍵程式碼/設定: ```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("LICENSE", licenseText); if (!lic.IsValidate()) throw new InvalidOperationException("License invalid"); // 啟用功能...


- 實測數據:
  - 改善前:序號破解率高,無法追蹤。
  - 改善後:需同時攻破私鑰與程式碼簽章,難度顯著增加。
  - 改善幅度:非法啟用事件下降(以授權服務端回報與支援工單統計)。

- 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

  • 直接原因:
    1. 只用公鑰加密(機密)不保證來源。
    2. 只用私鑰加密(來源)不保證機密。
    3. 無組合策略。
  • 深層原因:
    • 架構層面:缺少雙層流程。
    • 技術層面:加解密順序未設計。
    • 流程層面:未定義收發兩端職責。

Solution Design

  • 解決策略:發送方先用自己的私鑰加密(提供來源不可否認),再用接收方的公鑰加密(提供機密性);接收方用私鑰解開外層,再用發送方公鑰驗證內層。

  • 實施步驟:
    1. 發送端雙層加密
      • 實作細節:Sign(或對 Hash 簽章)後再 Encrypt。
      • 所需資源:RSA API。
      • 預估時間:1 天。
    2. 接收端雙層解密與驗章
      • 實作細節: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

  • 直接原因:
    1. 無互動式 API 文件。
    2. 測試無法方便帶自訂標頭(X-APIKEY、X-SESSION)。
    3. 缺乏雲端環境端到端驗證。
  • 深層原因:
    • 架構層面:測試工具整合不足。
    • 技術層面:Swagger 配置欠缺。
    • 流程層面:無回歸測試步驟。

Solution Design

  • 解決策略:以 Swagger(Swashbuckle)生成互動式頁面,在 UI 介面加入自訂 Header;部署至 Azure API Apps 進行雲端端到端驗證;建立最小回歸案例。

  • 實施步驟:
    1. 啟用與配置 Swagger
      • 實作細節:加入 X-APIKEY/X-SESSION 的 UI 欄位與傳遞。
      • 所需資源:Swashbuckle。
      • 預估時間:0.5 天。
    2. 雲端驗證
      • 實作細節:部署 AUTH 與 API 至 Azure API Apps,線上呼叫。
      • 所需資源:Azure 訂閱。
      • 預估時間:1 天。
  • 關鍵程式碼/設定:
    // 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 驗證),可直接用於實戰教學、專案演練與能力評估。






Facebook Pages

AI Synthesis Contents

- 原始文章內容
- 問答集
- 文章摘要
- 解決方案 / Case Study

Edit Post (Pull Request)

Post Directory