🎯 什麼情境該想到我

當你「訊息裡有太多欄位、或含有下游不該看到的敏感資料,想移除不需要的部分只留精華」的時候。

⚙️ 怎麼用(步驟 / 公式)

意圖:從訊息中移除不需要或不該外流的資料元素,簡化訊息內容。

做法 / 結構要點:

  • 定義要保留 / 移除的欄位規則。
  • 攔截訊息,濾掉多餘或敏感欄位(也可把複雜巢狀結構攤平成必要欄位)。
  • 送出精簡後的訊息。

★ 三個真實用途(第一個是法規要求,不是最佳實務)

① ★★ 移除敏感資料(PII、卡號、健保號、密碼)
   → ★ 這是合規要求:broker 有 retention、有備份、有日誌、有 DLQ
      → ★★ 訊息裡的 PII 會留在你想不到的五個地方
② ★ 縮小訊息(下游只需要三個欄位,不需要整個 200 欄的記錄)
   → 省頻寬、省反序列化、也避免下游依賴不該依賴的欄位
③ ★ 移除下游不該看到的欄位(多租戶、權限分級)

★★ 最重要的一點:預設要「白名單」不是「黑名單」

// ❌ 黑名單 —— ★★ 上游新增一個敏感欄位,你不會知道,它就漏出去了
delete(m, "credit_card")
delete(m, "ssn")
 
// ✅ 白名單 —— ★ 上游新增欄位時「預設不外流」
type PublicOrder struct {          // ★ 用一個明確的型別,而不是操作 map
    OrderID string `json:"order_id"`
    Total   Money  `json:"total"`
    Status  string `json:"status"`
}

★★ 這是這一頁最重要的一句:用「明確的輸出型別」而不是「從輸入刪欄位」。
Go 的 struct 天然就是白名單——沒宣告的欄位就不會被序列化出去。
黑名單式的 delete(map, key) 是 PII 洩漏的頭號機制。

★★ 五個容易漏掉 PII 的地方

① ★ 巢狀結構:你過濾了 order.customer.email,但 order.audit[].actor.email 漏了
② ★★ 自由文字欄位:notes / description / error_message 裡面常有人貼了完整資料
③ ★★ 錯誤訊息與日誌:err.Error() 可能含整個 request body
④ ★★ DLQ:失敗訊息帶著原始 body 進 DLQ —— ★ 而 DLQ 通常監控較鬆、權限較寬
⑤ ★ trace/span 的 attributes:有人把整個 payload 塞進 span

★ ④ 是最常被忽略的:你在主流程小心過濾,
但 DLQ 裡躺著未過濾的原始訊息,而且保留十四天、更多人有權限看。
→ ★ DLQ 的原始 body 也要考慮遮蔽,或至少加嚴權限與保留期。

★ 過濾發生在哪一端

位置說明
★★ 生產端就不發最安全。沒進到 broker 的資料不會外流
獨立的過濾器元件★ 但原始訊息已經在第一條通道裡了——那條通道本身就是洩漏點
消費端★★ 對 PII 沒有意義:資料已經流出去了

★★ 判準:這是「合規」還是「減量」?
合規(PII)→ 只能在生產端。加一個過濾器元件不解決問題,因為上游那條通道仍有完整資料。
減量(省頻寬)→ 中間或消費端都可以。

★ 遮蔽 vs 移除 vs 代換

// ① 移除:下游完全看不到
// ② ★ 遮蔽:保留可辨識性但不可還原    "4111...1111" → "**** **** **** 1111"
// ③ ★★ 代換(tokenization):換成一個 token,真值存在安全的地方
//    → ★ 這讓「需要時可以還原」與「訊息裡沒有明文」同時成立
//    → 這其實就是 [[寄物單]] 的思路用在敏感資料上
// ④ ★ 雜湊:可比對但不可還原(★ 注意:低基數欄位的雜湊可被暴力反推)

⚠️ 雜湊 email/手機號幾乎沒有隱私保護效果——可能值的空間小到可以窮舉。
需要真正的不可逆就要加 salt,而加了 salt 就不能跨系統比對。

★ 兄弟辨析

差別
訊息過濾器★★ 名字像但完全不同:它丟掉整則訊息;這個移除欄位
內容擴充器★ 反向:補上欄位
寄物單把內容搬到外部儲存,只留位址(★ 代換的同一思路)
訊息轉換器一般化的轉換;內容過濾器是「只做移除」的特例

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 與內容擴充器相反:這是做減法。

  • 過度過濾可能讓下游少了它其實需要的欄位。

  • 移除敏感資料時要確認合規要求,別誤留。

  • ★★ 用白名單(明確的輸出型別)而不是黑名單(從 map 刪欄位)。 黑名單在上游新增敏感欄位時會靜默漏出去。

  • ★★ 合規性的過濾只能在生產端。加中間過濾器不解決問題——上游那條通道本身就有完整資料。

  • ★★ DLQ 裡躺著未過濾的原始 body,保留十四天且權限較寬。這是最常被忽略的洩漏點。

  • ★ 容易漏的五處:巢狀結構、自由文字欄位、錯誤訊息/日誌、DLQ、trace attributes。

  • ★ 雜湊 email/手機號幾乎沒有隱私效果(可能值空間小到能窮舉)。

  • ★ 不要和 訊息過濾器 搞混:那個丟掉整則訊息,這個移除欄位。

  • 過濾掉的欄位如果下游其實需要,就會變成「回頭查」 → 又引入同步依賴(內容擴充器 的問題)。

  • GitHub Pages 這類公開發布也是同一個道理:留在任何可被快取的地方的資料,就當它永久存在。

🔗 相關工具