Read My Blog With JavaScript

Michael Lynch

用 JavaScript 閱讀我的部落格

你現在可以用用戶端 JavaScript 來閱讀我的部落格了。我不太確定你為什麼會想這麼做,但的確可以。

也許你想在自己的網站上加入一個部落格清單(blogroll),列出你喜愛部落格的最新文章,但又不想在伺服器端抓取資料。如果你想用 JavaScript 來顯示我最新的五篇文章標題,程式碼大概會像這樣:

fetch("https://mtlynch.io/index.xml")
  .then((response) => response.text())
  .then((str) => new DOMParser().parseFromString(str, "application/xml"))
  .then((data) => {
    const articles = [...data.querySelectorAll("item")].map((item) => ({
      title: item.querySelector("title").textContent,
      date: new Date(item.querySelector("pubDate").textContent),
    }));

    // Sort articles by date, newest to oldest.
    articles.sort((a, b) => b.date - a.date);

    // Print the titles of the 5 most recent articles.
    articles.slice(0, 5).forEach((article) => console.log(article.title));
  });

上述程式碼會產生以下輸出:

Refactoring English: Month 10
Get xkcd Cartoons at 2x Resolution
List of 2x-resolution xkcd Cartoons
I Once Appeared in The Old New Thing
Refactoring English: Month 9

這個點子來自Simon Willison(西蒙·威利森)在 Lobsters 上最近發表的一則留言

如何讓 JavaScript 讀取我的網站?

為了啟用 JavaScript 存取,我唯一需要做的就是為我的 RSS 摘要設定Cross-Origin Resource Sharing (CORS)(跨來源資源共用) HTTP 標頭。通常,阻止不同網站透過用戶端 JavaScript 讀取彼此內容的機制,就是same-origin policy(同源政策)

same-origin policy 規定,每個網站(origin)只能讀取與其自身網域相關的資源。因此,如果你造訪我在 mtlynch.io 上的部落格,而我的頁面上有 JavaScript 試圖從 chase.com 讀取你的銀行餘額,same-origin policy 就會禁止我頁面上的 JavaScript 存取該資訊。

為了讓其他網站能透過 JavaScript 讀取我的部落格,我必須為部落格的 RSS 摘要設定 CORS 標頭。這個部落格是一個目前代管於 Netlify 上的靜態網站,因此我必須修改 Netlify 的設定檔來為我的 RSS 摘要網址指定 CORS 標頭

[[headers]]
  for = "/index.xml"
  [headers.values]
    Access-Control-Allow-Origin = "*"
    Access-Control-Allow-Methods = "GET, HEAD, OPTIONS"
    Access-Control-Allow-Headers = "Content-Type"

可能會出什麼問題?

CORS 是一種安全機制,對於放寬面向網際網路的網站的安全限制,我一向會相當謹慎。但我花了一些時間評估風險,在我的情況下,我認為沒有任何實質的風險。

攻擊者能竊取機密資料嗎?

same-origin policy 的目的在於,如果使用者在網站 A 上有敏感資料,那麼除非網站 A 明確授權,否則網站 B 就無法存取其中任何資料。

我的部落格是一個沒有任何機密資訊的靜態網站。當我造訪 mtlynch.io 時,我看到的內容和其他人看到的完全一樣。因此,即使攻擊者誘使我在第三方網站上執行惡意的 JavaScript,程式碼也無法利用我在部落格上的權限,因為我在這裡根本沒有任何特殊權限。

我確實使用TalkYard 來提供嵌入式留言功能,而且我在那裡擁有管理員權限,但我為 RSS 摘要設定的 CORS 設定並不會影響 TalkYard。

攻擊者能對我發動 DDoS 攻擊嗎?

一開始,我以為攻擊者可能會濫用 CORS 設定來對我的網站發動 DDoS 攻擊。如果攻擊者讓數百萬人造訪一個頁面,而該頁面在背景透過 JavaScript 不斷請求我的 RSS 摘要,會怎麼樣呢?

後來我才意識到,這樣的 DDoS 攻擊本來就已經可行。CORS 只控制第三方網域是否能讀取請求的結果,但根本不會阻擋請求本身。無論 CORS 設定為何,任何網域都可以對其他任何網域發出 GET 和 POST 請求。

攻擊者能冒充我的網站嗎?

我考慮過的另一種攻擊是冒充。訪客可能會前往 evil.example.com,而那裡的伺服器可以回傳 JavaScript,在訪客的瀏覽器中重建我的部落格,即使網址列顯示的仍是 evil.example.com。

這種攻擊的確可能成功,但無論我的 CORS 設定為何,都有更簡單的方式來冒充我的部落格。冒充者可以執行一個會將請求轉發到我部落格的 HTTP proxy,這是更簡單的冒充方式。或者,他們也可以直接擷取我的網站內容並放到別處代管。

為什麼要讓 JavaScript 讀取我的部落格?

沒有人要求我為 RSS 摘要啟用 CORS,所以我也不確定這是否真的對任何人有好處。但我喜歡開放的網路,而這是一個讓其他網站與我的網站互相協作的有趣方式,所以我想,何樂而不為呢?

如果你因為這項變更而用我的 RSS 摘要做了什麼有趣的事,歡迎告訴我

原文由 Michael Lynch 發布

本文章由 muse-spark-1.2-contributor 進行翻譯