退訂連結不該把 email 放進網址
客戶專案踩坑
Ricky-
08 月 22,2026

每封信底部都要有「退訂」。最直覺的寫法是 /unsubscribe?email=someone@x.com&token=…——網址帶著 email 和一個簽章。但這個設計有兩個藏在細節裡的問題。

不安全 /unsubscribe?email=someone@x.com&token=hmac(email) ✗ email 留在日誌 / 歷史 / referrer ✗ 固定簽章永不失效 → 誰拿到都能退掉他 安全版 /unsubscribe?t=9f3c…隨機、與 email 無關 GET 只顯示「確認退訂」頁 · 按下的 POST 才真的退訂
把 email 從網址拿掉、改用不可猜的隨機 token,再用 GET/POST 兩段式。

兩個問題

一、email 攤在網址上。網址會被記進伺服器日誌、瀏覽器歷史、referrer,甚至被轉寄——等於把訂閱者的信箱到處留痕。

二、退得掉別人。如果 token 是用 email 算出來的固定簽章,它永不失效;任何拿到那條連結的人(轉寄、側錄、日誌)都能隨時退訂那個人。

安全版設計

不可猜的隨機 token。每個訂閱者發一組跟 email 無關的隨機 token,存在資料庫。退訂網址只帶 token、完全不帶 email——退不了別人,也不外洩信箱。

兩段式:GET 只確認、POST 才退訂。很多信箱與防毒會自動「點開」信裡的連結去掃描;如果 GET 就退訂,會被這些掃描器誤觸。所以 GET 只回一個「確定要退訂嗎」的頁面,按下按鈕送出的 POST 才真的改狀態。

// 退訂只認隨機 token;GET 安全、POST 才有副作用
GET  /unsubscribe?t=<random>   → 顯示「確認退訂」頁(不改狀態)
POST /unsubscribe  { t }       → 查到訂閱者 → 設為已退訂 + 通知站長

// token 產生:與 email 沒有任何可推導關係
unsubToken = crypto.randomBytes(32).toString("hex"); // 唯一、索引
…/unsubscribe?t=9f3c… (GET · 不改狀態) 確定要退訂新文章通知嗎? 確認退訂 ↳ 按下 = POST,這一步才真的退訂
GET 只給一個確認頁;掃描器就算自動點進來,也不會動到任何人的訂閱狀態。

眉角

  • 「GET 要安全、冪等」不是教條。這裡就是它保護你不被信箱掃描器誤退訂的實例。
  • 不透露、不重複。無效 token 一律回同一個「連結無效」頁,不告訴對方 token 是否存在;已退訂者再點也不重複通知站長。
  • 順手加值:退訂成功也通知站長「是誰退的」,掌握名單變化。
帶得走的一句話

退訂連結是少數「陌生人手上就有」的入口。把 email 從網址拿掉、用不可猜的隨機 token、再用「GET 確認 / POST 執行」擋掉自動掃描——退訂就從「誰都能退掉誰」變成「只有本人點得動」。

Tags:
資安電子報


相關文章
驗收 AI 寫的碼:只信 typecheck 是不夠的
驗收 AI 寫的碼:只信 typecheck 是不夠的
ricky - 2026-08-22T09:12:18.570047Z
驗收 AI 寫的碼有層級:typecheck 只是地板,往上是讀懂 diff、runtime 測真實路徑、對關鍵邏輯寫確定性測試。
從零開始製作一個ip查詢網站-第二章 獲取使用者的IP
從零開始製作一個ip查詢網站-第二章 獲取使用者的IP
chris - 2025-11-29T05:54:37Z
想知道自己的 IP 是多少,並為後續地理定位做準備嗎?這篇文章完整教你如何在 React 網頁中抓取使用者公開 IP,說明為什麼瀏覽器無法直接提供真實 IP,並示範使用免費的 ipify API 快速...
一鍵發版背後:三個 repo 的分工
一鍵發版背後:三個 repo 的分工
ricky - 2026-07-09T02:00:00Z
一顆「發版」按鈕,背後牽動 fleet-console、部署後端與目標服務三個 repo。本文拆解版本號為什麼不能由前端計算、docker build --build-arg 如何無條件帶入 APP_...
訂閱電子報
隨時掌握最新的創業故事與設計開發過程
內容包含來自麒航團隊的日常分享、專業知識與工具推薦,助你了解更多創業背後的思維與技術。
麒航私房推薦
Clelereve Blog LogoClelereve Blog LogoClelereve Blog Logo
廣告區
Clelereve Blog Logo
聯絡我們
任何合作或問題請洽:
clelereve@gmail.com
Follow us
Copyright © 2025 blog.clelereve.com - All Rights Reserved
Frontend Version: -- | Backend Version: --
創業實驗筆記 - Clelereve Blog | 退訂連結不該把 email 放進網址 | Clelereve Blog