聯絡表單收到一堆亂碼和數字?排查 FormSubmit 的兩大常見雷區

技術分享

AI 文章延伸

AI 幫你讀這篇文章

選擇平台後可直接帶入閱讀脈絡,快速整理重點、補齊盲點,並延伸到同站相關文章。

我們最近在官網上線了新的聯絡表單,為了減少維護後端的成本,我們採用了 FormSubmit 這個主打「靜態網頁也能收表單」的無後端服務。原本以為只要接上 AJAX 就萬事太平了,沒想到隔幾天信箱裡卻出現一封標題寫著「Codotx ???????!」,內文佈滿問號與詭異數字的信件。

FormSubmit 寄來的亂碼與機器人灌水測試信

原本我們還擔心是不是系統錯誤導致我們遺失了哪位重要客戶的商業詢問,經過一番排查,才發現原來是我們一次踩到了處理表單時常見的兩個雷區。

第一個坑:FormData 與 AJAX 的編碼迷失

看到信件裡大量的 ????,一開始還以為是資料中途被截斷。比對結構後才發現,這些問號其實是對應表單裡的中文欄位名稱(像是「姓名」、「訊息內容」等等)。出問題的原因,源自於我們在前端「攔截」表單送出的作法。

因為我們不想讓使用者送出表單後,硬生生被跳轉到 FormSubmit 的內建感謝頁面,所以改用 Javascript 的 fetch API 在背景發送表單,並直接把原生的 new FormData(form) 塞進 request 的 body 裡。

如果是一般的表單提交,瀏覽器會主動幫你處理好所有的字元編碼;但在 AJAX 搭配 multipart/form-data 的情境下,只要伺服器端稍微沒有準確捕捉到邊界(Boundary)或編碼資訊,這些中文字元就會直接被判定為無效字元,通通變成問號。這種狀況下,資料在主機端轉碼的瞬間就永久遺失了,連搶救也搶救不回來。

怎麼解決的? 很簡單:不要直接丟原生 FormData,把它轉成標準的 JSON 物件。只要在 fetch 的參數加上 Content-Type: application/jsonAccept: application/json,就能確保 UTF-8 資訊在傳輸到 FormSubmit 解析的過程中安然無恙。只改了這幾行,中文就復活了。

const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());

fetch("https://formsubmit.co/ajax/[email protected]", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Accept": "application/json"
  },
  body: JSON.stringify(data)
})

第二個坑:無視規則的無情灌水機器人

中文顯示亂碼的問題解決後,我們試著去破譯這封信裡的內容。結果發現:原本在前端限定只能輸入少量字元的「姓名」欄位,居然被填入了 526312,而應該是「電子郵件」或「訊息」的地方,則塞了 82969221362 這樣不知所云的數字。

我們的網頁明明做了前端的 Require 必填與 Input Type 的格式驗證,為什麼還會收到這種明顯不合格的資料?

結論很殘酷:因為這是機器人(Spam Bot)送出的。

機器人根本不會打開瀏覽器乖乖填寫表單,而是用程式腳本暴力爬取網頁,找出 FormSubmit 的發送網址,然後直接對伺服器發射 POST 請求。對於它們來說,你在前端寫再多 HTML5 驗證都形同虛設。

而之所以會被攻擊,是因為我們當初為了讓「真正的使用者」有最流暢的體驗,把 FormSubmit 預設的 ReCAPTCHA 驗證給手動關掉了(透過設定隱藏欄位 _captcha=false)。我們等於在網路上開了一個沒有配置警衛的大門,難怪機器人暢通無阻。

AJAX 的限制與蜜罐(Honeypot)救援 既然被攻擊了,直覺的作法是把 ReCAPTCHA 打開。但這裡我們又差點踩到另一個坑:FormSubmit 原生並不支援 AJAX 模式下的 reCAPTCHA。如果硬把它打開,反而會導致伺服器回傳驗證 HTML 頁面,讓我們的 JSON AJAX 解析失敗,最後真正的使用者在送出表單時永遠只會看到「發生網路錯誤」。

為了解決這個兩難,我們採用了更聰明、且完美相容於 AJAX 的「蜜罐機制(Honeypot)」。 我們在表單程式碼裡埋了一個隱藏欄位:

<input type="text" name="_honey" style="display:none" />

真實的使用者因為有 CSS 的 display: none 而看不見這個欄位;但只看 HTML 原始碼的機器人,會傻傻地把資料填進去。FormSubmit 只要偵測到 _honey 有值,就會立刻判定為垃圾信件並無聲丟棄。這讓我們在保持順暢無跳轉的使用者體驗同時,成功擋下了 99% 的機器人攻擊。

小結

這次的表單踩坑經驗,讓我們學到兩個血淋淋的教訓:

  1. 處理帶有非英文字元的無後端表單 API 時,JSON 格式永遠比 FormData 更穩。 只要是 AJAX 呼叫,強烈建議一律轉成 JSON。
  2. 防機器人機制千萬不能省,但也要考慮適配性。 如果你的專案高度依賴無後端服務的 AJAX 串接,傳統圖形驗證碼(Captcha)可能會徹底破壞流程。這時候不妨換個思路,利用「隱藏欄位」作為蜜罐誘餌,反而是一個既低成本、好實作,又能優雅解決問題的絕佳方案。

作品案例

看看我們打造的產品與專案。從 WordPress 外掛到 AI 客服方案,每一個作品都是實戰經驗的累積。

瀏覽作品案例

服務項目

WordPress 開發、WooCommerce 電商、LINE 整合、AI 解決方案,依據你的需求提供最適合的技術服務。

瀏覽服務項目

Contact

聯絡我們

若你有任何技術需求、專案諮詢或合作想法,歡迎隨時與我們聊聊(首次諮詢免費)。

  • 想打造 WordPress 網站或 WooCommerce 電商
  • 需要 LINE 整合或 AI 功能導入
  • 有產品點子想找技術合夥人一起實現
  • 既有網站需要改版升級或效能優化
  • 尋找長期穩定的技術顧問合作夥伴