🎯 什麼情境該想到我
當你「訊息裡有太多欄位、或含有下游不該看到的敏感資料,想移除不需要的部分只留精華」的時候。
⚙️ 怎麼用(步驟 / 公式)
意圖:從訊息中移除不需要或不該外流的資料元素,簡化訊息內容。
做法 / 結構要點:
- 定義要保留 / 移除的欄位規則。
- 攔截訊息,濾掉多餘或敏感欄位(也可把複雜巢狀結構攤平成必要欄位)。
- 送出精簡後的訊息。
★ 三個真實用途(第一個是法規要求,不是最佳實務)
① ★★ 移除敏感資料(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 這類公開發布也是同一個道理:留在任何可被快取的地方的資料,就當它永久存在。
🔗 相關工具
- 內容擴充器 Content Enricher(同家族的相反操作,補進欄位)
- 寄物單 Claim Check(同家族,改把大內容外存只留取件單)
- 企業整合模式
- 訊息過濾器 —— ★ 名字像但是丟掉整則訊息
- 內容擴充器 —— 反向操作
- 寄物單 —— 代換/tokenization 的同一思路
- 訊息轉換器 —— 一般化的轉換
- 死信通道 —— DLQ 是常被忽略的洩漏點