iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0
Build on Google AI

《30天打造喵語日誌:Gemini API × Vibe Coding 實戰》系列 第 24

Day 24:【資料庫資安】Firestore 安全規則與金鑰環境管理

  • 分享至 

  • xImage
  •  

無後端架構的資安痛點

在傳統的三層式網站架構中,資料庫通常隔離在後端伺服器(Node.js / Go / Java)後面。後端可以透過 Session 或 Token 逐一驗證請求的合法性,再決定是否允許存取資料庫。

但在以 Firebase 為主的無後端架構(BaaS)中,前端應用是直接連線至 Cloud Firestore。

如果在建立資料庫時沿用了官方預設的「測試模式」,例如:

allow read, write: if true;

那麼任何只要打開瀏覽器開發者工具(F12),取得 Firebase Config 的人,都能輕易撰寫腳本讀取或竄改所有使用者的私密日記。

為了徹底杜絕資料外洩與跨使用者越權存取的風險,今天將透過 Firestore Security Rules 與環境變數管理,為《喵語日誌》築起第二道嚴密的資料庫防線。

為什麼需要 Firestore Security Rules?

在缺乏傳統後端作為中介層的情況下,所有資料庫請求皆來自客戶端,任何人也都能在瀏覽器中檢視前端設定。

若只依賴前端程式碼做權限防護,攻擊者只需修改前端邏輯即可輕易繞過。

因此,為了徹底杜絕資料外洩與跨使用者越權存取的風險,必須仰賴運行在 Google 伺服器端的 Firestore Security Rules 作為雲端守門員,結合嚴謹的環境變數管理,為《喵語日誌》築起第二道嚴密的資料庫防線。

設計「最小權限原則」的安全規則

在 Cloud Firestore 中,安全規則是運行在 Google 雲端伺服器上的存取守門員。

我前往 Firebase Console 的「Firestore Database > 規則」頁面,將寬鬆的測試規則替換為嚴格遵循「最小權限原則(Principle of Least Privilege)」的規則設定:

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    // 嚴格限制:只有通過驗證且 UID 與資料夾相符的使用者本人,才能讀寫自己的 diaries
    match /users/{userId}/diaries/{diaryId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }

    // 預設拒絕其他所有未明確開放的路徑
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

這套規則的核心邏輯在於 request.auth.uid == userId

它確保了每位使用者(包含透過 Firebase Auth 匿名登入的使用者)在發起資料庫請求時,其 Token 內攜帶的專屬 uid 必須與路徑中的 {userId} 完全一致。

如果請求者的 UID 與目標路徑不符,雲端將直接阻斷連線。

而第二段規則則明確關閉了所有未定義路徑的讀寫權限,防止有心人士遍歷資料庫或嘗試存取其他集合。

資安防禦實測:授權存取 vs 惡意越權攔截

部署完成後,我進行了合法寫入與模擬惡意越權存取的雙重驗證。

1. 合法使用者正常讀寫

在前端介面中,我以已登入使用者的身分發送日常心情日記:

今天很早就起床了,現在好累...

系統順利完成圖片與文字分析,並在控制台印出存檔成功的 Log:

✅ 日誌已成功存入 Firestore, Doc ID: ...
📥 成功即時同步 4 筆雲端日記

https://ithelp.ithome.com.tw/upload/images/20260824/20178708RiHKrKbimC.png
這證明了只要請求者的 UID 與存取路徑匹配,安全規則便會正常放行,不影響合法操作。

2. 越權存取阻擋實測

接著,我在前端程式中模擬攻擊者試圖偽造未授權的假 UID(fake_attacker_888),強制讀取他人私密日記的惡意請求:

// src/services/firebase.ts 片段
export async function testUnauthorizedAccess() {
  try {
    const fakeRef = collection(
      db,
      "users",
      "fake_attacker_888",
      "diaries"
    );

    await getDocs(fakeRef);
    console.log("❌ 漏洞:居然讀取成功了!");
  } catch (err: any) {
    console.warn(
      "🛡️ 成功防禦!Firestore 拒絕越權存取:",
      err.message
    );
  }
}

在控制台執行此函式後,Firestore 雲端立即識別出發起者的 auth.uid 與目標路徑 fake_attacker_888 不符,毫不猶豫地阻斷請求並回傳權限不足的警告:
https://ithelp.ithome.com.tw/upload/images/20260824/20178708TEZzR3ISQX.png
▲ 控制台成功攔截惡意跨目錄讀取,回傳 Missing or insufficient permissions,證明雲端防線已確實生效。

前端金鑰保護與環境變數管理

除了資料庫層級的規則防護,前端專案本身的機密管理也需要建立正確的資安觀念。

Firebase Config 的公開性本質

許多初學者會誤以為 Firebase API Key 被打包在前端 JavaScript 是資安漏洞。

事實上,Firebase API Key 僅是用於識別專案的客戶端標識符,真正的存取控制完全依賴於:

  • Firestore Security Rules

  • Firebase Auth 機制

  • 使用者 Token 的驗證

因此,即使 Firebase Config 被公開,只要安全規則設定正確,攻擊者仍然無法讀取或竄改他人的資料。

Gemini API Key 的環境隔離

不同於 Firebase Client Key,Gemini API Key 屬於具備調用額度與計費屬性的金鑰。

如果這把金鑰外洩,攻擊者可能濫用額度,造成不必要的費用或服務中斷。

因此,我嚴格透過 .env.env.local 進行環境變數管理,並在 .gitignore 中加入 .env* 相關規則:

# .gitignore
.env
.env.local
.env.*.local

這樣可以確保私密金鑰絕不會被提交至公開的 GitHub 儲存庫中。

同時,在程式碼中也只透過 import.meta.env 讀取環境變數,避免將金鑰硬編碼在原始碼中。

這次實作的心得

無後端架構為現代前端開發帶來了極高的開發效率,但也將資安架構的思維核心轉移到了雲端規則的設計上。

Firestore Security Rules 本質上就是運行在 Google 邊緣伺服器上的輕量安全中介層。

這次實作讓我深刻體會到:資安是多層次防護的結合,前端可以透明公開,但後端規則必須遵循最小權限原則;而金鑰管理則需依據性質分級防護,並透過實際的越權測試驗證防禦能力。

只要透過嚴謹的路徑劃分與 UID 條件校驗,即便前端代碼完全暴露在瀏覽器中,也能以極低的維護成本實現完善的資料隔離與隱私保障。

結語

在連續完成了「AI 提示詞防禦」與「Firestore 資料庫安全規則」後,《喵語日誌》無論在對話邊界還是資料隱私層面,都已具備了健全的保護網。

穩固了前後端安全性之後,明天將正式跨出本機開發環境,邁入雲端部署階段!我們將配置生產環境變數、執行 Production 打包編譯,將專案從 Localhost 正式推向全世界,取得屬於《喵語日誌》的正式公開 HTTPS 網址,讓這隻陪伴貓咪真正走進更多人的日常生活中。

明天見,喵~ 🐾


上一篇
Day 23:【AI 資安】Prompt Injection 防禦與 System Instruction 設計:讓貓咪守住人設防線!
下一篇
Day 25:雲端實戰!Vercel 自動化部署與生產環境 Gemini API 除錯紀實
系列文
《30天打造喵語日誌:Gemini API × Vibe Coding 實戰》25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言