回首頁
Reference for Physicians

引用回响机制:教学与资安设计指南

结论先说:医师之间的网站互引,价值不在流量,而在于把单向发言变成可验证的专业对话。做法上,关键只有一件事——伺服器实际去对方页面确认连结存在,其余的资安设计,都是为了让这个「去确认」的动作不会反过来伤害自己的网站。

本頁記錄 drkao.org 自網站成立至今在引用迴響功能上的完整實作與資安考量,歡迎其他醫師與架站人員自由參考、引用或直接套用於自己的網站。

Concept

什麼是「引用迴響」?

引用回响(Web Mention)是一种网站之间互相「知会」的机制:当 B 医师在自己的文章中引用并连结到 A 医师的某篇文章,A 医师的那篇文章下方就会自动出现一则纪录,显示 B 医师的文章标题、网站名称与连结。 它让原本单向的连结变成双向的对话。读者在读 A 医师的论述时,可以顺着回响看到其他医师如何延伸、补充或在临床上如何应用;而 B 医师也因为被列在原文之下而获得曝光。这是一种不需要平台、不需要帐号、只靠双方网站就能成立的专业互引。

  • ・不是留言板:迴響來自另一個已公開發布的網站頁面,而不是匿名輸入的一段文字,因此天然帶有署名與可追溯性。
  • ・不是單純的反向連結:反向連結只有搜尋引擎看得到;引用迴響是讀者在頁面上就能直接看到並點擊的內容。
  • ・不是內容農場式互推:系統會實際抓取對方頁面,確認頁面上真的存在指向本文的連結,才會登記。

Value

為什麼醫療內容特別需要它?

医学资讯的可信度,很大一部分建立在「谁在说、以什么为依据、有没有人可以对话」。单独一篇文章再完整,读者也难以判断它在整个专业社群中的位置。引用回响把这个位置具体地呈现出来。

  • ・呈現專業對話:同一個題目,耳鼻喉科、神經內科、中醫的觀點可以彼此連結,讀者看到的是一個討論網絡,而非孤立的斷言。
  • ・分流責任邊界:節目或短文負責「容易進入」,官網延伸文負責補上適用範圍、證據與安全紅旗;互引讓讀者能走完整條路徑。
  • ・利於 AI 檢索(AIEO):AI 摘要在判斷內容權威性時,會參考被哪些同領域來源引用。雙向、可驗證的引用關係比單向連結更有說服力。
  • ・累積長期資產:迴響紀錄留在文章下方,隨時間累積,形成他人難以複製的專業信任證據。

Proposal

真正對等的做法:編輯型互指

自助登记的引用回响区块,本质上接近读者投稿,因此本站已依规范为该区块的连结标记 rel="ugc nofollow"——它的价值在于真实导流与关系建立,而不是搜寻权重的交换。若要形成真正对等、双方都受益的引用关系,正确的做法是「编辑型互指」:在自己文章的正文里,用一段话认真带到对方的观点,并附上连结。 这不只是挂连结,而是把球丢给对方:读者读到一个角度不足的地方,正好被引导到另一位医师补上的那一块。本站文章下方的「医界对话」区块,就是专门呈现这种正文引用的位置,其连结为正式引用,不加 nofollow。

  • ・雙方都在正文:引用寫在文章內容裡,而不只是頁尾的連結清單,讓引用有語意脈絡。
  • ・雙方 canonical 正確:每篇文章的 canonical 必須指向自己,而非首頁。指向首頁等於告訴搜尋引擎這頁不是獨立內容,頁上的連結權重也會被稀釋。
  • ・雙方語意真的相關:例如結構性眩暈與能量調養,一個講結構、一個講能量,互補才成立;主題無關的互引對雙方都沒有幫助。
  • ・雙方可被抓取:純 HTML 可讀最理想。若網站為前端渲染,應確認搜尋引擎的渲染索引狀況,並理解多數 AI 爬蟲不執行 JavaScript。

歡迎直接來信提出互指合作:在您的文章中引用本站觀點,本站也會在相關主題的正文中回引您的文章,並列入「醫界對話」。

How to

其他醫師如何登記引用?只有三個步驟

  • ・第一步:在您自己的網站文章中,用一般的超連結指向本站的文章網址,例如 https://drkao.org/sanctuary/ent-five-elements。連結必須是真實可見的 <a> 連結,不要只寫成純文字。
  • ・第二步:確認您的文章已公開發布,網址在無痕視窗下也能正常開啟(草稿或需登入的頁面無法通過驗證)。
  • ・第三步:回到本站被引用的那篇文章,在頁面下方「引用迴響」區塊貼上您文章的網址,按送出。系統會即時抓取並驗證,通過後您的文章標題與連結會立刻顯示在該篇文章之下。

若送出後顯示「在該頁面上找不到本文的連結」,通常是三種情況:連結還沒發布上線、連結寫成了純文字、或連結指向的是舊格式網址。確認頁面原始碼中確實含有本文網址後再送出即可。

技術與資安

Architecture

整體架構與資料流

整個機制只需要一個後端端點。前端把「被引用的文章 ID」與「來源網址」以 POST 送到後端,所有驗證、抓取與寫入都在伺服器端完成,前端不直接讀取外部網站,也不直接寫入資料庫。

STEP 1

前端送出

讀者在文章下方貼上自己的文章網址,以 POST 送出 post_id 與 source_url。

STEP 2

網址檢查

解析網址格式、限定 http/https、封鎖內網位址,並以 DNS 解析確認指向公開 IP。

STEP 3

抓取與驗證

伺服器端抓取該頁 HTML,確認頁面上確實存在指向本文的連結,並擷取標題與摘要。

STEP 4

去重與登記

比對是否已登記過同一組(文章、來源網址),通過後寫入並立即回傳顯示。

Security 01

SSRF 防護:最容易被忽略的風險

這類功能的本質是「讓陌生人指定一個網址,由我的伺服器去打它」。若不設限,攻擊者可以請伺服器去存取內網服務或雲端 metadata 端點,讀取憑證。這是 OWASP 列名的伺服器端請求偽造(SSRF)。防護分三層。

  • ・協定白名單:只接受 http 與 https,拒絕 file://、gopher://、ftp:// 等可被用來讀取本機檔案或繞過檢查的協定。
  • ・位址黑名單:封鎖 localhost、127.0.0.0/8、10.0.0.0/8、172.16–31、192.168.0.0/16、169.254.0.0/16(雲端 metadata)、100.64/10(CGNAT)、多播位址,以及 IPv6 的 ::1、fc00::/7、fe80::/10 與 ::ffff: 映射位址。
  • ・DNS 解析驗證:只檢查字串是不可靠的:攻擊者可以用 nip.io 這類動態 DNS 或自己的網域,把公開網域解析到 127.0.0.1。因此必須先把主機名解析成實際 IP,再用同一套黑名單檢查解析結果。
先解析 DNS,再以同一套黑名單檢查實際 IP
const ips = await resolveIps(source.hostname);
if (ips.length === 0 || ips.some(isBlockedAddress)) {
  return Response.json({ error: '不支援此網址' }, { status: 400 });
}
  • ・redirect: 'manual':抓取時關閉自動跟隨轉址。否則對方可以回一個 302 把伺服器導向內網,繞過前面所有檢查。
  • ・回應大小上限:只讀取前 500KB 的 HTML,避免對方回傳無限長的內容耗盡記憶體。
  • ・封鎖自家網域:拒絕來源網址本身就是自己網站的情況,避免自我引用與內部路徑探測。

Security 02

權限控管:分清誰能做什麼

一個網站上的端點,權限層級並不相同。把它們混為一談,是最常見的資安破口。本站的分法如下。

  • ・公開端點:登記引用是開放的,因為它的安全性來自「內容驗證」而非「身分驗證」——沒有連結到本文就無法登記,任何人都偽造不了對方網站上的內容。
  • ・管理者端點:群發文章給訂閱者這類操作,必須在函數內第一行就驗證呼叫者的 role 是 admin,而不是只在前端隱藏按鈕。前端隱藏不是權限控管。
  • ・系統任務端點:排程觸發的自動化任務(每日新知生成、歡迎信寄送)不屬於任何登入者。這類端點以環境變數中的系統金鑰驗證,並允許管理者手動觸發,其餘一律拒絕。
  • ・金鑰不落地:系統金鑰只存在於平台的環境變數,絕不寫進工作流定義檔或前端程式碼。工作流只呼叫一個統一入口函數,由該函數在伺服器端注入金鑰。
  • ・資料列權限(RLS):在資料層再設一道:迴響紀錄公開可讀,但只有管理者能新增、修改、刪除;訂閱者名單只有管理者能讀。寫入一律經由伺服器端的服務身分執行。
共用授權模組:系統金鑰或管理者,兩者皆非即拒絕
const denied = await requireSystemOrAdmin(base44, payload);
if (denied) return denied;

Security 03

驗證與反垃圾:讓造假無利可圖

傳統的 Trackback 之所以在部落格時代被垃圾訊息淹沒,原因是它只接收對方送來的資料,從不查證。避免重蹈覆轍的關鍵,是把「信任」建立在可驗證的事實上。

  • ・雙向連結驗證:唯一的信任基礎:伺服器實際抓取來源頁面,確認 HTML 中存在指向本文的連結。對方無法在自己網站之外的頁面偽造這件事,因此無需帳號也能防止冒名。
  • ・支援多種本文網址格式:驗證時必須接受該文章的所有合法網址形式(ID 網址與短網址 slug)。只認一種格式,會讓正確引用的人被誤判為未引用——這也是本站實際踩過的坑。
  • ・重複登記去重:以(文章 ID、來源網址)組合查詢既有紀錄,重複送出回傳 409,不會產生重複列表。
  • ・中繼資料而非全文:只擷取 og:title、og:site_name、author、og:description,並各自截斷長度上限。不複製對方全文,避免版權與內容注入問題。
  • ・冪等性設計:所有會產生外部副作用的操作(例如寄送歡迎信)都先寫入「已執行」標記再執行,確保重試或重複觸發時不會重複寄送。
  • ・錯誤訊息不外洩:對內網位址、不存在的文章、抓取失敗等情況,一律回傳中性的使用者訊息,不揭露內部路徑或解析結果。

Checklist

給架站者的實作檢查清單

  • ・端點以 POST 接收,不用 GET 傳遞網址參數
  • ・只接受 http / https 協定
  • ・封鎖私有網段、loopback、link-local 與雲端 metadata 位址
  • ・以 DNS 解析後的實際 IP 再檢查一次黑名單
  • ・抓取時 redirect: 'manual',並限制回應大小
  • ・驗證來源頁面確實含有指向本文的連結,接受本文所有合法網址格式
  • ・以(文章、來源網址)去重,重複回傳 409
  • ・只擷取中繼資料並截斷長度,不存全文
  • ・寫入資料一律經伺服器端服務身分,並設定資料列權限
  • ・管理者操作在函數內驗證 role,不依賴前端隱藏
  • ・排程端點以環境變數金鑰驗證,金鑰不寫入任何檔案
  • ・有外部副作用的操作先標記後執行,確保冪等

想實際試一次?

在您的文章中連結到本站任一篇文章,再到該篇文章下方的「引用迴響」區塊貼上您的網址送出即可。 歡迎從聖所文章列表挑選相關主題開始。