在大多數的系統中,首頁通常會有大大的「註冊帳號」按鈕。但在我們的寶可夢追蹤系統中,這是一個專為「自己與幾位親密好友、分身小帳」設計的專屬天地。因此,我們做了一個大膽的決策:不開放對外註冊,改採管理員後台加入的封閉式系統。
為什麼我們要放棄常見的開放註冊機制?
| 考量點 | 封閉式系統 (本專案採用) | 開放式註冊系統 |
|---|---|---|
| 資料庫資源 | 完全可控。只有您認識的朋友能進入,不怕 Serverless 資料庫空間被無意義的測試資料塞滿。 | 風險較高。惡意機器人可能瞬間註冊上萬個假帳號,消耗免費額度的雲端資源。 |
| 系統維護成本 | 極低。不需要處理「忘記密碼發送信件」、「Email 驗證信」、「手機簡訊認證」等繁瑣機制。密碼忘記直接找管理員重設就好。 | 極高。需要串接第三方信件發送服務 (如 SendGrid),還要處理垃圾信夾的問題。 |
| 資安風險 | 高安全性。未授權者連大門都進不來,系統的 API 只有內部幾個人在敲打。 | 需要做各種防撞庫、防機器人 (CAPTCHA) 的機制。 |
對於這種自用的 Side Project 來說,封閉式系統絕對是最明智的選擇!
我們建立了兩張表:system_users (負責登入) 與 player_accounts (遊戲內的好友本尊/小帳):
CREATE TABLE system_users (
user_id TEXT PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL, -- 密碼絕對不能存明碼!
role TEXT DEFAULT 'user' -- 分為 admin 或 user
);
而在 Express 中,我們寫了一支只允許管理員建立新帳號的 API:
import bcrypt from 'bcryptjs';
// 建立帳號 (此 API 未來會用 Middleware 擋住,只准 Admin 呼叫)
router.post('/admin/users', async (req, res) => {
const { username, password } = req.body;
// 核心重點:用 bcrypt 進行密碼雜湊,單向加密
const salt = await bcrypt.genSalt(10);
const passwordHash = await bcrypt.hash(password, salt);
await db.execute({
sql: 'INSERT INTO system_users (username, password_hash) VALUES (?, ?)',
args: [username, passwordHash]
});
res.status(201).json({ message: '朋友帳號建立成功!' });
});

資料庫內的畫面,
password_hash欄位變成一長串亂碼,密碼已被安全加密。
我們成功建立了一道安全的城牆,並確保使用者的密碼被安全地加密。帳號有了,明天我們就要來發放讓朋友進入系統的「數位通行證」:JWT!