Day 25 | 環境變數:把密鑰從程式碼裡拿出來
JWT_SECRET目前還寫在程式碼裡,如果推上GitHub,任何人都能偽造token。今天把它移出去。
今天做的事
安裝dotenv,新增.env存放真正的密鑰,另外建一個.env.example放提示文字(這個會上傳,讓別人知道要設定什麼)。config.js改成沒有設定就直接報錯:
require('dotenv').config();
const JWT_SECRET = process.env.JWT_SECRET;
if (!JWT_SECRET) {
throw new Error('缺少環境變數 JWT_SECRET,請建立 .env 檔案');
}
密鑰用Node內建的crypto產生 64 字元的隨機字串。再用git check-ignore -v .env確認.gitignore真的擋住了它,輸出.gitignore:3:.env就代表成功。最後補上README.md,寫明如何安裝與執行。
觀察
卡關
我以為重啟伺服器後,之前登入的token會失效,測試卻發現沒有。後來才理解:JWT是無狀態的,伺服器不用記得誰登入過,只要密鑰沒變,簽名就驗得過,重啟並不影響。要讓舊token失效,必須是換掉密鑰。這也呼應了第十九天選JWT的理由:部署在隨時會重啟的主機上,使用者不會頻繁被登出。反過來說,密鑰一旦洩漏,別人就能偽造任何人的token,所以才不能寫進程式碼。
心得
原本以為環境變數只是設定檔,現在知道它其實是在區分可以公開的程式碼跟不能公開的秘密。
Day 26 | 整體測試:把自己當成第一個使用者
不寫新功能,把註冊、登入、新增、編輯、完成、刪除、篩選、搜尋、兩個帳號隔離,全部照清單跑一遍。
今天做的事
列出測試表逐項確認,並特別測試幾個邊界狀況:重複註冊、錯誤密碼、空白標題、壞掉的JSON、登出後的行為。
觀察
卡關
測試時發現無法新增待辦事項。打開Network分頁,POST /api/todos 回傳404,內容是JSON 格式的API 路徑不存在。Express自己的404是一整頁HTML,這個JSON是我在server.js 最後寫的兜底路由回應的,代表這個請求跑完所有路由都沒有對上。我用同一個方法排查:看Network的狀態碼和回應內容、檢查server.js的路由順序、確認有沒有舊的伺服器程序占著port。
心得
這次學到最有用的一件事是看回應的格式也能判斷是誰回的:HTML是框架自己的,JSON是我自己寫的。測試不是為了證明沒問題,而是為了找出沒想到的問題。
Day 27 | 部署前準備:PORT、start 指令與健康檢查
網站在自己電腦上跑得好好的,丟到雲端之前要先改幾個地方。
今天做的事
app.set('trust proxy', 1);
const PORT = process.env.PORT || 3000;
app.get('/health', (req, res) => res.json({ status: 'ok' }));
資料庫路徑也改成可以用DB_PATH環境變數指定。
觀察
心得
在我的電腦上能跑跟在別人的電腦上能跑中間,隔著一堆平常看不見的假設,例如port、環境變數、啟動方式。今天就是一項一項把這些假設變成設定。