第八章:駭客最愛找的漏洞!環境變數 (.env) 與資安防護

在前面幾章,我們學習了怎麼申請 Supabase,拿到了資料庫的 URL 跟 API Key。未來你也可能會申請 Gmail 發信的密碼、或是 OpenAI 的 Token。

請立刻停下手邊的動作聽好:有一個絕對不能犯的致命錯誤,就是把這些「秘密字串」直接寫在程式碼裡,然後上傳到公開的 GitHub 上! 如果你犯了這個錯,你的 API 金鑰就會變成駭客的免費提款機。


🔒 什麼是環境變數?為什麼要用它?

想像你把一把保險箱的鑰匙 (例如 GMAIL_PASS="super-secret-123") 直接寫在程式碼 send-email.ts 裡面。 當你把程式碼傳給同事,或是上傳到 GitHub,全世界都能看到這把鑰匙!只要有心人搜尋一下,他就可以用你的名義發送數萬封垃圾信,或是把你的資料庫全部刪光。

為了解決這個問題,工程師發明了 環境變數 (Environment Variables) 的概念。 我們會建立一個名為 .env 的隱藏檔案,把所有的密碼集中存放在這裡:

# .env 檔案
NEXT_PUBLIC_SUPABASE_URL="https://your-project.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsIn..."
OPENAI_API_KEY="sk-proj-xxxxxxxxxxxx"
GMAIL_PASS="abcd-efgh-ijkl"

然後在程式碼中,我們不寫死密碼,而是用「代號」去呼叫它。 在 Next.js / React 生態系中,我們會這樣寫:

// 程式碼中這樣寫
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const openaiKey = process.env.OPENAI_API_KEY;

當程式跑起來時,系統會自動去 .env 檔案裡找出對應的密碼填進去。這樣一來,程式碼裡面就非常乾淨,沒有任何機密資訊了。


🛡️ .gitignore:保命的隱形斗篷

光是把密碼放進 .env 檔案還不夠!如果你在執行 git commit 時,把 .env 檔案本身也一起上傳到 GitHub,那剛才做的一切就全部白費了!

這時候你需要 .gitignore 檔案。它的功能就像是海關的黑名單,告訴 Git(版本控制系統):「這些檔案太私密,絕對不可以備份出去!」

打開專案根目錄的 .gitignore,你會看到裡面通常已經寫了:

node_modules/
.next/
.env
.env.local
.env.*

只要有這幾行,當你上傳程式碼時,Git 就會自動無視 .env 檔案。你的秘密永遠只會留在你自己的本機電腦上。

🔥 [Vibe Coder 專業習慣] 建立 .env.example 既然 .env 不會上傳,那當你的同事 (或是未來的你) 在另一台電腦下載這份專案時,怎麼知道要填哪些密碼? 專業的做法是建立一個名為 .env.example 的檔案,並把它上傳到 GitHub。裡面只留變數名稱,不留密碼:

# .env.example
NEXT_PUBLIC_SUPABASE_URL="請填寫 Supabase 專案 URL"
OPENAI_API_KEY="請填寫你的 OpenAI API Key"

這樣別人下載專案後,只要複製這個檔案並改名為 .env,然後填入自己的密碼就能順利運行,這就是業界最高標準的協作禮儀。


⚠️ [常見地雷區] 為什麼在前端抓不到環境變數?

這是新手最常崩潰的問題。你在 .env 裡面寫了 SECRET_TOKEN="123",但在 React 組件裡面用 console.log(process.env.SECRET_TOKEN) 印出來卻是 undefined

解法:理解「安全前綴」的概念! 現代的前端框架 (如 Next.js 或 Vite) 為了保護你的資安,預設會封鎖所有環境變數,不讓它們流出到使用者的瀏覽器上

  • 後端專用 (私密):如果你寫 OPENAI_API_KEY,這個變數只能在伺服器端 (Server Components 或 API Routes) 被讀取。如果前端嘗試讀取,會拿到 undefined。這是對的,因為你不應該把 OpenAI 金鑰送到使用者的瀏覽器上!
  • 前端可用 (公開):如果你真的需要讓前端 (瀏覽器) 讀取這個變數 (例如 Supabase 的 Anon Key,這是設計上可以公開的),你必須加上特定的前綴:
    • 在 Next.js 中,必須加上 NEXT_PUBLIC_ 前綴 (例如 NEXT_PUBLIC_SUPABASE_URL)。
    • 在 Vite 中,必須加上 VITE_ 前綴 (例如 VITE_SUPABASE_URL),讀取時用 import.meta.env.VITE_SUPABASE_URL

🚨 救命!我不小心把密碼上傳到 GitHub 了怎麼辦?

新手最常犯的錯就是漏了設定 .gitignore,不小心把帶有真實密碼的 .env 上傳到了公開的 GitHub。

請特別注意:駭客有寫專門的機器人,24 小時在 GitHub 上掃描外洩的金鑰! 只要外洩超過幾分鐘,你的 AWS 雲端帳單可能就會暴增幾十萬,或是你的 OpenAI 額度被瞬間刷爆。

如果你發現自己不小心外洩了密碼,千萬不要試圖在 GitHub 上刪除檔案或是修改歷史紀錄,那太慢而且沒用 (歷史紀錄永遠會留存)

你唯一要做的,只有一件事:立刻去源頭把該密碼作廢 (Revoke) 並產生一組新的!

  • 如果是 OpenAI 金鑰,立刻登入 OpenAI 後台刪除該把金鑰。
  • 如果是 Supabase,去設定後台重新生成一組 API Key。
  • 如果是 Gmail,去 Google 帳戶後台刪除應用程式密碼。 當舊密碼失效後,駭客拿到了也只是一堆廢紙。

💼 [商業應用場景] 區分開發與正式環境

學會環境變數,你就具備了接下大型商業專案的能力。 在真實的企業開發中,不可能開發測試跟正式上線都用同一個資料庫,萬一測試時不小心把客戶的真實訂單刪掉怎麼辦?

這時環境變數就是你的救星。你可以在本機設定一個連接「測試資料庫」的 .env.local。 然後在 Vercel 部署平台上,進入 Settings -> Environment Variables,填入「正式生產資料庫」的密碼。 同一套程式碼,在你的電腦上跑就會連到測試庫,部署上線就會自動連到正式庫。這就是現代軟體工程的 CI/CD (持續整合/持續部署) 的第一步!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!