Firebase 前端API 是安全的
Firebase 前端 API Key 真的可以公開嗎?
TL;DRFirebase 前端 config(包含 apiKey)本來就設計成可以公開。它不是 secret,而是 identifier(像資料庫 URL),用來告訴 Google 你要連哪個專案。真正的安全靠 Firebase Security Rules + App Check,跟 API key 完全無關。
常見誤解
// 看到這段在 React 前端,直覺反應:「天啊,Stripe / OpenAI key 都不能放前端,Firebase 怎麼這樣?」
const firebaseConfig = {
apiKey: "AIzaSyB-XXX...",
authDomain: "my-app.firebaseapp.com",
projectId: "my-app",
storageBucket: "my-app.appspot.com",
messagingSenderId: "1234567890",
appId: "1:1234567890:web:xxx"
};
這不是 secret。這跟 DB URL https://my-app.firebaseio.com 一樣是公開識別資訊。每個 iOS / Android Firebase app 也都把同樣的 config 包進 binary 裡,可以被反組譯看到。
為什麼 這 OK
Stack Overflow 官方解答(Frank van Puffelen, Firebase 工程師)Is it safe to expose Firebase apiKey to the public?The
apiKeyin this configuration snippet just identifies your Firebase project on the Google servers. It is not a security risk for someone to know it. In fact, it is necessary for them to know it, in order for them to interact with your Firebase project.
重點:
- apiKey 只是標識 Firebase project,讓 client SDK 知道要連哪個 server
- 它 沒有授權能力,不像傳統 API key 是「持有 = 有權限」
- 每個訪客都需要它 來跟你的 Firebase 互動,本來就會發送到瀏覽器
真正保護你的資料的東西
1. Firebase Security Rules(主要防線)
// Firestore Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// 文章:已登入才能讀,只有作者能寫
match /posts/{postId} {
allow read: if request.auth != null;
allow create: if request.auth != null
&& request.auth.uid == request.resource.data.authorId;
allow update, delete: if request.auth != null
&& request.auth.uid == resource.data.authorId;
}
// 個人資料:只有自己能讀寫
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
Security Rules 在 Firebase 伺服器端強制執行,client 怎麼改 code 都繞不過。這才是真正的安全層。
2. App Check(2021 年加入,進階防線)
import { initializeAppCheck, ReCaptchaV3Provider } from 'firebase/app-check';
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaV3Provider('your-recaptcha-site-key'),
isTokenAutoRefreshEnabled: true,
});
App Check 確保請求來自你註冊的 app(iOS / Android / Web),阻擋:
- 用 curl / postman 直接打你 Firebase API
- 用別人寫的 scraper 抓你資料
- 拿你 config 用在自己的 app 偷流量
推薦組合Security Rules 控制「誰能存取什麼」+ App Check 控制「誰能發請求」 — 兩者搭配才完整。
3. Authentication
Security Rules 通常基於 request.auth 判斷權限,所以要先開 Firebase Auth 並讓使用者登入。詳見 Firebase 驗證 儲存到useContext。
4. Quotas / Budget Alerts
Firebase 控制台可以設 每日請求上限 跟 預算警示,防止有人惡意用你的免費額度跑光。Spark plan 本身免費就有上限,Blaze plan 一定要設 budget alert。
但有一種狀況真的要 隱藏
後端 SDK / Service Account Key 必須保密!
// ❌ 永遠不要把這個放前端
const serviceAccount = require('./service-account-key.json');
import admin from 'firebase-admin';
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
Service Account 有 admin 權限,可以繞過所有 Security Rules、操作整個 project。只能放 server-side(Cloud Functions / Express API / Next.js API route)。
| 類型 | 可公開? | 用途 |
|---|---|---|
| 前端 config / apiKey | ✅ 可公開 | client SDK 識別 project |
| Service Account Key (JSON) | ❌ 絕對不能 | server-side admin 操作 |
| OAuth Client Secret | ❌ 不可 | server-side OAuth 流程 |
進階:用 Hosting SDK auto-config 隱藏
如果不想把 config 寫死在 source code 裡,可以用 Firebase Hosting SDK auto-configuration:
<!-- 不寫 config,自動從 hosting 載 -->
<script src="/__/firebase/init.js"></script>
只是把 config 從 client source code 搬到 runtime URL,本質仍是公開的。這只是降低 git 上有這 config 的「資訊量」,不是真的隱藏(F12 Network 還是看得到)。
最常見的 Firebase 安全錯誤
Top 3 真實爆炸案例
- Security Rules 設成
allow read, write: if true;開發時方便,上線忘記改 → 整個 DB 任何人都能讀寫- 沒設 App Check → 別人爬蟲整天撈你 Firestore,一個月燒光 quota
- Storage Rules 沒擋上傳 → 有人上傳 GB 級檔案到你 bucket 燒光免費額度
上線前必做:
- Security Rules 通過 emulator 測試
- 開 App Check
- 設 Budget Alert
- Console → Firestore Rules 看到 紅色「測試模式倒數」警告 必須處理掉