1 / 30
AI Coding 初學者實作課

API Key 安全與
Vercel Functions

用 Vercel Serverless Functions 代替前端呼叫 OpenRouter,讓學生的作品真的可以連上免費模型,同時學會最重要的秘密管理觀念。

Serverless Functions Environment Variables OpenRouter free model API Key 不外洩
學完會得到什麼

今天不是只學 Vercel,是學「秘密怎麼放」

能動起來

學生的前端作品可以送出問題,經由自己的後端路由呼叫 OpenRouter,取得 AI 回覆。

能部署

知道 Vercel 上要在哪裡新增 `OPENROUTER_API_KEY`,以及修改環境變數後為什麼要重新部署。

能避開大坑

理解 API key 不能出現在前端程式、GitHub repo、瀏覽器 DevTools、公開 log 與分享截圖中。

課堂核心句:前端可以被看見;後端才適合保管秘密。

先講危險

API key 不是普通字串

API key 就像你的服務門禁卡。拿到它的人,可能可以用你的額度、打你的 API、產生成本,甚至存取不該看的資料。

  • 成本風險:別人拿你的 key 去大量呼叫。
  • 名譽風險:不當內容或濫用行為記在你的帳號下。
  • 資料風險:某些服務 key 可能同時有讀寫資料庫、檔案或管理權限。
不要這樣

const apiKey = "sk-..."

放在 `main.js`、`index.html`、前端 `.env`,最後都可能被使用者看到。

改成這樣

process.env.OPENROUTER_API_KEY

只在 serverless function 讀取,前端永遠只打自己的 `/api/chat`。

一張圖記住架構

正確路線:瀏覽器 → 你的後端 → OpenRouter

  • 使用者在網頁輸入文字,前端把文字送到自己的 `/api/chat`。
  • Vercel Function 在伺服器端讀取 `OPENROUTER_API_KEY`。
  • Function 代替前端呼叫 OpenRouter,並把結果整理後回傳給網頁。

學生只要記住:前端送需求,後端加秘密。

瀏覽器經由 serverless function 呼叫 AI 模型供應商的安全架構示意圖

示意圖:GPT Image 生成,依課程內容繪製。

最容易誤解的地方

為什麼不能直接在前端 call OpenRouter?

View Source

打包後的 JS 仍然會下載到使用者電腦。只要在檔案裡,就可能被搜尋。

DevTools

瀏覽器 Network、Sources、Console 都可能看到請求、header 或變數。

GitHub

公開 repository、commit history、fork 都會讓秘密很難完全收回。

分享截圖

上課、發問、錄影時,畫面上的 token 可能被截走。

判斷規則:只要會被瀏覽器下載,就不是秘密。

Unsafe vs Safe

同一個功能,差在 key 放在哪裡

做法結果
前端 JS 直接放 key 使用者可從打包檔或 Network 找到 key。
把 key commit 到 GitHub 即使刪掉檔案,commit history 仍可能留下紀錄。
Vercel env + function 代呼叫 前端只知道你的 API 路由,不知道 OpenRouter key。
不安全與安全 API key 放置方式的對照示意圖

示意圖:GPT Image 生成,依課程內容繪製。

Vercel Serverless Functions

Vercel Function 是你的「輕量後端」

對初學者來說,可以先把 serverless function 想成:不需要自己架伺服器,但可以寫一個後端 API。

  • 放在專案的 `/api` 資料夾。
  • 部署到 Vercel 後會變成網站路徑,例如 `/api/chat`。
  • 程式在伺服器端執行,所以可以讀取環境變數。
專案結構frontend + api
my-ai-demo/
├─ index.html
├─ style.css
├─ main.js
└─ api/
   └─ chat.js   ← 後端路由

依 Vercel Node.js Runtime 文件:`/api` 內的 function 會由 Vercel build and serve。

Vercel Environment Variables

在 Vercel 後台新增
OPENROUTER_API_KEY

  1. 進入 Vercel 專案,打開 Settings → Environment Variables
  2. Key 填 `OPENROUTER_API_KEY`,Value 貼上 OpenRouter API key。
  3. 建議開啟 Sensitive,並選擇要套用的環境:Production、Preview、Development。
  4. 儲存後重新部署;環境變數的修改只會套用到新的 deployment。
Vercel 新增環境變數介面

操作畫面:Vercel Environment Variables 文件截圖。

本機開發

本機用 `.env.local`,但不能 commit

.env.local只放在自己電腦
OPENROUTER_API_KEY=sk-or-v1-xxxxxxxx
OPENROUTER_SITE_URL=http://localhost:3000
OPENROUTER_SITE_NAME=Student AI Demo
.gitignore避免上傳秘密
.env
.env.local
.env.*.local
node_modules/
.vercel/
提醒學生:如果 key 曾經 commit 到 GitHub,不能只刪掉檔案,要立刻到服務商後台 revoke / rotate key,再建立新的 key。
OpenRouter Free Models Router

教學可先用 `model: "openrouter/free"`

OpenRouter 的 Free Models Router 會從可用的免費模型中挑選合適模型。對初學者教學來說,它能降低「先選哪個模型」的負擔。

  • API endpoint:`https://openrouter.ai/api/v1/chat/completions`
  • 認證方式:`Authorization: Bearer <OPENROUTER_API_KEY>`
  • 模型欄位:`model: "openrouter/free"`

免費模型適合學習、展示、低流量實驗;正式產品需要看 rate limit、可用性與成本。

OpenRouter 模型頁面與免費模型列表

操作畫面:OpenRouter Models 頁面截圖,顯示免費模型項目。

資料流

學生要背的不是平台,是資料怎麼走

1. Browser

送出使用者輸入。這裡只有 prompt、表單資料、按鈕狀態,不放 secret。

2. `/api/chat`

讀 `process.env.OPENROUTER_API_KEY`,加上 Authorization header,呼叫模型供應商。

3. OpenRouter

回傳 AI 結果。你的 function 再把必要資訊傳回前端。

前端永遠不需要知道 OpenRouter API key。

Step 1: 後端 route

建立 `api/chat.js`

這支檔案是「安全代理人」:接收前端訊息,讀 env,代替前端呼叫 OpenRouter。

  • `request.body` 只包含學生輸入。
  • `process.env.OPENROUTER_API_KEY` 只在 function 裡讀。
  • 回傳時整理成前端需要的格式。
api/chat.jsVercel Node.js Function
module.exports = async (request, response) => {
  if (request.method !== "POST")
    return response.status(405).json({ error: "Use POST" });

  const message = request.body?.message || "";

  const ai = await fetch("https://openrouter.ai/api/v1/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.OPENROUTER_API_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: "openrouter/free",
      messages: [{ role: "user", content: message }]
    })
  });

  const data = await ai.json();
  const answer = data.choices?.[0]?.message?.content || "";
  return response.status(ai.status).json({ answer, raw: data });
};
main.js前端只呼叫自己的 API
async function askAI(message) {
  const res = await fetch("/api/chat", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ message })
  });

  const data = await res.json();
  if (!res.ok) throw new Error(data.error || "API error");
  return data.answer || "目前沒有回覆";
}
Step 2: 前端呼叫

前端不碰 OpenRouter

前端只知道你的網站有一個 `/api/chat`。它不需要知道 OpenRouter 的 endpoint,也不應該知道 API key。

學生常問:「那前端還是可以看到 `/api/chat` 啊?」可以。這個路由不是秘密;秘密是路由背後的 `OPENROUTER_API_KEY`。
Deploy 流程

從零到可用的 7 個步驟

  1. 在 OpenRouter 建立 API key,先不要貼到程式碼裡。
  2. 在專案新增 `api/chat.js`,讓 serverless function 代呼叫模型。
  3. 前端改成 `fetch("/api/chat")`,不要直接打 OpenRouter。
  4. 本機開發用 `.env.local`,並確認 `.gitignore` 已忽略 env 檔。
  5. 推到 GitHub,再匯入到 Vercel。
  6. 到 Vercel Project Settings 新增 `OPENROUTER_API_KEY`。
  7. 重新部署,打開 Production URL 測試。
檢查點

學生卡住時,先問這 6 題

路由有沒有被部署?

網址列試 `/api/chat`,至少應該看到 405 或 JSON 錯誤,而不是 404。

環境變數名稱對嗎?

Vercel key 名稱必須和程式裡的 `process.env.OPENROUTER_API_KEY` 完全一致。

有重新部署嗎?

Vercel 文件指出 env 變更只會套用到新的 deployment。

前端打的是 `/api/chat` 嗎?

如果前端直接打 OpenRouter,通常會遇到 key 外洩或 CORS 類問題。

OpenRouter key 有效嗎?

401 多半是 key 錯、沒貼完整、被撤銷,或沒有帶 Authorization header。

免費模型可用嗎?

免費模型可能有 rate limit 或暫時不可用;教學時要準備備用模型。

常見錯誤碼

看到錯誤,不要先亂改

狀況可能原因先檢查
401key 無效或沒有帶 AuthorizationVercel env 名稱與值
404function 沒部署或路徑錯`api/chat.js` 位置
405用 GET 打到只收 POST 的 route前端 `method`
429rate limit 或免費額度限制等候、換免費模型或降低頻率
500後端程式錯、env 缺失、JSON 解析失敗Vercel Function Logs
不要把錯誤完整貼到公開論壇,因為 log 裡可能包含 request、header 或部分 token。
教學時可要求學生交「錯誤碼 + 發生步驟 + 已遮蔽截圖」,不要交完整 key 或完整 log。
命名陷阱

`NEXT_PUBLIC_`、`VITE_`、`PUBLIC_` 通常是公開變數

許多前端框架會把特定前綴的環境變數打包進瀏覽器端程式。這類變數適合放公開設定,不適合放 API key。

危險名稱

VITE_OPENROUTER_API_KEY

NEXT_PUBLIC_API_KEY

這些通常會變成前端可讀。

後端名稱

OPENROUTER_API_KEY

DATABASE_URL

只在 server-side function 讀取。

Key 管理習慣

真正的產品,不只是不外洩

最小權限

能只給讀取權就不要給管理權;能限定服務範圍就不要全開。

分環境

Development、Preview、Production 使用不同 key,降低單點外洩影響。

可撤銷

知道去哪裡 revoke / rotate key,外洩時能快速換掉。

加限制

可加每日額度、rate limit、使用者登入、伺服器端驗證。

教學作品也要讓學生養成產品習慣:秘密管理是工程基本功,不是上線後才補。

Vercel 只是範例

其他平台通常也有同一個概念

平台通常放哪裡程式怎麼讀
VercelProject Environment Variables`process.env.MY_KEY`
NetlifyEnvironment variables`process.env.MY_KEY`
Cloudflare WorkersSecrets / Bindings`env.MY_KEY`
GitHub ActionsRepository Secrets`${{ secrets.MY_KEY }}`
Docker / ServerRuntime env 或 Secret Manager環境變數或 secret mount

語法會變,原則不變。

  • 不要寫死在 repo。
  • 不要送到瀏覽器。
  • 不要印在公開 log。
  • 讓後端在執行時讀取。
課堂實作任務

讓學生做一個「AI 小幫手」

功能規格

  • 一個輸入框:學生輸入一句問題。
  • 一個送出按鈕:呼叫 `/api/chat`。
  • 一個回覆區:顯示 OpenRouter 回傳內容。
  • 錯誤時顯示「目前無法取得回覆,請稍後再試」。

驗收標準

  • 在 GitHub 搜尋不到 `sk-` 或 API key。
  • 瀏覽器 Network 看不到 OpenRouter key。
  • Vercel 後台有 `OPENROUTER_API_KEY`。
  • 重新部署後,Production URL 可以得到 AI 回覆。

實作題最好把「安全驗收」列入分數,學生才會把 API key 當成正式工程問題。

可貼給學生的 prompt

讓 AI 幫忙寫,但要指定安全架構

如果學生使用 AI coding 工具,prompt 要明確要求「前端不能保存 API key」。

重點不是禁止使用 AI,而是讓 AI 產出的架構符合安全要求。
Prompt template給 AI coding 工具
請幫我做一個前端網頁,使用者輸入問題後取得 AI 回覆。
請使用 Vercel Serverless Function:

1. 前端只能 fetch("/api/chat")
2. OpenRouter API key 只能在 api/chat.js 用
   process.env.OPENROUTER_API_KEY 讀取
3. 不要把 API key 寫在任何前端檔案
4. OpenRouter model 使用 "openrouter/free"
5. 請加入錯誤處理與簡單 loading 狀態
公開與秘密

哪些可以在前端?哪些不可以?

可以公開
  • 網站名稱、主題色、公開圖片 URL。
  • 你的 `/api/chat` 路徑。
  • OpenRouter 模型名稱,例如 `openrouter/free`。
  • 不涉及權限的 UI 設定。
不能公開
  • API key、database password、service token。
  • 可管理帳號或計費的 secret。
  • private webhook secret。
  • 學生或使用者的個資資料。

判斷不確定時,先當作秘密處理,再請老師或工程同伴確認。

Log 與 Debug

除錯時也不能把 key 印出來

不要log secret
console.log(process.env.OPENROUTER_API_KEY);
console.log(request.headers);
console.log(fullOpenRouterResponse);
可以log status only
console.log("OpenRouter status:", ai.status);
console.log("Has API key:", Boolean(process.env.OPENROUTER_API_KEY));
console.log("Message length:", message.length);

如果要請同學或老師幫忙 debug,先遮蔽 token。不要把完整 header、完整 env、完整 `.env.local` 貼出來。

避免濫用

Key 藏好後,還要保護自己的 `/api/chat`

即使 key 沒外洩,如果任何人都能無限制打你的 route,仍然可能消耗你的額度。

  • 加入簡單 rate limit:同一 IP 或同一使用者每分鐘限制次數。
  • 限制輸入長度:例如 `message.length < 1000`。
  • 需要時加登入:只讓課堂學生或註冊使用者使用。
  • 記錄必要指標:錯誤碼、次數、耗時,不記錄 secret。
max 1000 chars
10 req / min / user
optional for class demos
status, latency, no key
萬一外洩

API key 外洩時的處理順序

順序動作原因
1停用舊 key先切斷濫用可能。
2建立新 key舊 key 不能再信任。
3更新 Vercel env 並 redeploy新 deployment 才會讀到新值。
4清理公開內容與 Git history降低再次被掃到的機會。
5檢查用量與帳單確認外洩期間是否被濫用。

標準答案:外洩後不要相信舊 key 還安全。

教師講解順序

建議 50 分鐘教學流程

時間活動重點
0-8 分講 API key 是什麼秘密不是普通設定
8-18 分畫資料流前端公開,後端保密
18-30 分建立 `api/chat.js`function 代呼叫 OpenRouter
30-40 分Vercel 設定 envKey、Value、環境、redeploy
40-50 分測試與 debug錯誤碼、log、不要貼 key
最後要帶走的 5 句話

把這 5 句當成 API key 安全口訣

  • 前端不是保險箱,瀏覽器能下載的都可能被看見。
  • API key 放在環境變數,不放在程式碼。
  • 前端打自己的 `/api/chat`,後端才打 OpenRouter。
  • Vercel 是例子,任何平台都要找它的 secret/env 設定。
  • 外洩就 rotate,不要補救舊 key。
資料來源與延伸閱讀

本簡報引用的官方文件

Vercel Functions

Node.js runtime、`/api` directory、Request / Response、function helper。

https://vercel.com/docs/functions/runtimes/node-js

Vercel Environment Variables

環境變數是 source code 外的 key-value pairs、會加密儲存、變更只套用到新 deployment、本機可用 `.env.local`。

https://vercel.com/docs/environment-variables

OpenRouter Quickstart / Free Models Router

`/api/v1/chat/completions`、`Authorization: Bearer`、`model: "openrouter/free"`、免費模型限制。

https://openrouter.ai/docs/quickstart
https://openrouter.ai/docs/guides/get-started/free-models-router-playground