規則不公開狀態下控制 firestore

前言

上一篇介紹如何使用 koa.js 來接上 firestore,但是那篇文章其實有一個很嚴重的安全性問題,那就是規則其實是公開的,所以這篇將會記錄該如何在不公開狀態下透過 firebase 帳號權限來控制 firestore。

調整規則

首先如果是參照前面製作過來的話,那麼規則絕對會是公開的,所以要麻煩改成不公開。

1
2
3
4
5
6
7
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}

不公開

撰寫 firestore 相關檔案

首先先新增一隻檔案叫 firebase_admin.js,內容如下(會稍微與 firebase_client.js 有點像) ↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const admin = require("firebase-admin");
require('dotenv').config();

const serviceAccount = {
type: process.env.FIREBASE_TYPE,
project_id: process.env.FIREBASE_PROJECT_ID,
private_key_id: process.env.FIREBASE_PRIVATE_KEY_ID,
private_key: process.env.FIREBASE_PRIVATE_KEY,
client_email: process.env.FIREBASE_CLIENT_EMAIL,
client_id: process.env.FIREBASE_CLIENT_ID,
auth_uri: process.env.FIREBASE_AUTH_URI,
token_uri: process.env.FIREBASE_TOKEN_URI,
auth_provider_x509_cert_url: process.env.FIREBASE_AUTH_PROVIDER_X509_CERT_URL,
client_x509_cert_url: process.env.FIREBASE_CLIENT_X509_CERT_URL
}

admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});

module.exports = admin;

firebase_admin

如果不知道自己的以上 type、project_id、private_key_id 等等,請到左上角齒輪 → 服務帳號 → Firebase Admin SDK 生成新的私密金鑰

私密金鑰

如果不想這麼麻煩的引入也可以用另一種寫法 ↓

1
2
3
4
5
6
7
8
9
const admin = require('firebase-admin');

const serviceAccount = require('path/to/serviceAccountKey.json');

admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});

module.exports = admin;

但是我建議使用 ENV 的作法會比較好。

補充雷點

如果出現 Error: Failed to parse private key: Error: Invalid PEM formatted message. 的錯誤訊息

Invalid PEM formatted message

這個問題很簡單,只需要開啟 .env 檔案將 FIREBASE_PRIVATE_KEY 的金鑰加上雙引號即可解決

Router

接下來 router 的地方就比較簡單了,只需要引入並加上 firestore() 即可開始使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const firebaseAdmin= require('../connection/firebase_admin');
const db = firebaseAdmin.firestore();

router.get('/api', async (ctx, next) => {
var data = {
name: 'Angeles',
state: 'CA',
country: 'TW'
};
var setDoc = db.collection('LA').doc('cities').set(data);
await ctx.render('api', {
title: 'Hello Plase Login!'
})
})

firestore

接下來只需要訪問 http://localhost:3000/api 就可以看到 firestore 更新囉~

firestore

參考文獻

firebase doc

0%