py程式設計(三)課程網站
第 11 週 · 單元 4-1 · 專案二

社團活動報名平台(下):權限、個資與上線

加上幹部專屬功能,確認社員碰不到不該碰的東西,最後部署到 Vercel+Neon。今天的測試重點是「被拒絕的情況」。

W11報名平台權限+上線

本週結束時你會

今天的時間安排

0:00–0:40功能 3【自己做】幹部功能與權限
0:40–1:10步驟 ⑤ 驗收【自己做】自動測試與「攻擊自己的網站」
1:10–1:20休息
1:20–2:00步驟 ⑥ 上線【跟著做】Neon、SECRET_KEY、線上驗收
2:00–2:30同組互測、Demo、專案回顧

功能 3:幹部功能與權限

自己寫提示詞。需求:寫一個 officer_required 裝飾器(未登入導到登入頁、已登入但不是幹部回應 403);幹部可以新增活動(名稱 1–40 字、日期、名額 1–500)、在活動頁看到「查看報名名單」、下載名單 CSV(Excel 打開不能亂碼)。

操作正確結果
阿明開 /officer/events/new403「這個頁面只有幹部可以使用」
阿明開工作坊的名單網址403
未登入開名單網址導到登入頁
社長看工作坊名單阿明、小美、阿哲,依報名時間排序
社長下載 CSV、用 Excel 開啟中文正常,有序號、暱稱、報名時間
社長新增名額 0 的活動名額必須是 1 到 500 的整數

只把按鈕藏起來不算權限控制。社員看不到「新增活動」按鈕,但只要知道網址還是打得開。每一個幹部頁面的路由,都必須在伺服器端檢查角色。

CSV 在 Excel 亂碼:檔案開頭要加上 UTF-8 的 BOM(),Excel 才會用 UTF-8 讀取。

步驟 ⑤ 驗收:測試「被拒絕」的情況

提示詞 Antigravity
請先讀 PROJECT.md 與需求說明書的驗收標準。用 pytest 寫 tests/test_app.py,每個測試使用獨立資料庫並放入示範資料,至少涵蓋:
1. 首頁的剩餘名額
2. 資料庫中的密碼不是明碼
3. 錯誤密碼登入失敗(401)
4. 未登入報名會被導到登入頁
5. 額滿、重複報名被擋下;取消後人數減少
6. 社員開幹部頁面 403;幹部可以看名單與下載 CSV
7. 註冊時暱稱重複、密碼太短被擋下
有測試失敗時先告訴我原因,不要修改預期值。

參考解答 10 項測試(含下方互測清單中的 XSS 與外部網址導向),在 SQLite 與 PostgreSQL 18 上各執行一次,20 項全部通過。

攻擊自己的網站(同組互測)

和隔壁同學交換網址,用社員帳號試著做到下列事情。每一項都應該失敗:

第 4 項是 XSS(跨站腳本)。Jinja 預設會把 < > 轉成文字,所以 Flask 網站通常是安全的;但若 AI 在範本中使用了 |safe 或 Markup,就會出事。成功攻擊到同學網站的組別,請他們示範並說明修正方法,這比任何講解都有效。

步驟 ⑥ 上線:Neon 加上 SECRET_KEY

  1. 推上 GitHub,在 Vercel 匯入專案,照第 8 週的方式加入 Neon,並在 Neon 的 SQL Editor 建立資料表。
  2. 示範帳號的密碼雜湊無法用 SQL 手寫,請對 Antigravity 說:「產生一個 neon_seed.sql,用 Postgres 語法建立需求說明書的示範帳號(密碼先用 werkzeug 雜湊好)與活動。這個檔案不要加入 Git。」再貼到 SQL Editor 執行。
  3. 設定 SECRET_KEY:在自己電腦的終端機執行下面的指令,產生一串隨機字元,貼到 Vercel → Settings → Environment Variables,名稱 SECRET_KEY,然後重新部署。
python -c "import secrets; print(secrets.token_hex(32))"

SECRET_KEY 用來保護登入狀態。知道它的人可以偽造任何人的登入,包含幹部。它不能出現在程式碼、GitHub 或 AI 對話框中;只放在 Vercel 的環境變數。

線上驗收正確結果
首頁四場活動與正確的剩餘名額
註冊新帳號 → 報名 → 隔 10 分鐘再看報名紀錄仍在
重新部署後再打開仍保持登入(SECRET_KEY 沒變)

本週檢核

第 12 週預告:同一份 PROJECT.md,換成 Next.js 重做吃貨站。