
這章要學會什麼
- 把一支現成的服務整理成一份「可以被審核的呼叫契約」:名稱、分類、用途、網址、方法、認證方式、輸入輸出規格、請求範例、版本號。
- 分清楚「存檔檢查」(格式不對就不能存)跟「送審前檢查」(內容沒填齊就不能送審)是兩道不同的關卡。
- 做出草稿的新增、修改、刪除跟「建立新版本」,並保證已送審的版本不能再改、會員只能改自己的草稿。
- 把上游服務要用的密鑰加密存起來,證明密鑰的明文不會出現在任何一個頁面上。
先備知識
要先完成第 4 章:能用不同帳號登入。要知道什麼是 JSON 格式,以及「JSON Schema」這種用來描述「一份 JSON 資料該長什麼樣子」的規格書——本章只會用到其中幾個最基本的關鍵字。
觀念白話講
為什麼要把一支服務整理成「呼叫契約」
平台之後要代替 AI 助理去呼叫這些服務。如果登記的時候只寫了一個網址,平台根本不知道要帶什麼參數、參數長什麼樣子、要不要帶密鑰——所以登記的其實是一份完整的契約:
| 欄位 | 誰會用到 | 缺了會怎樣 |
|---|---|---|
| 名稱、分類、用途說明 | 使用者在目錄裡搜尋;之後映射成 AI 工具的說明文字 | AI 不知道什麼時候該用這個工具 |
| 網址、呼叫方法 | 之後的安全閘道靠這個組出請求 | 呼叫不到、或用錯方法呼叫 |
| 認證方式 | 安全閘道決定要不要帶密鑰標頭 | 上游服務直接回絕 |
| 輸入規格(JSON Schema) | 之後驗證 AI 傳來的參數合不合規格 | AI 亂傳參數,錯誤一路打到上游 |
| 輸出規格、請求範例 | 使用者理解回傳內容、審核者評估風險 | 審核者無從判斷這支服務會做什麼 |
| 版本號 | 申請、授權、呼叫全部綁定同一個版本 | 網址改了卻沒人重新審核 |
用 JSON Schema 當作「參數的規格書」
JSON Schema 是用 JSON 格式來描述「一份資料該長什麼樣子」的公版寫法。例如「商品查詢」的輸入規格可以寫成:這是一個物件,裡面可以有一個叫 keyword 的欄位,這個欄位必須是文字、最多 50 個字。這門課要做兩種驗證:一是「這份規格書本身寫得對不對」(例如型別名稱有沒有拼錯),二是「填的範例資料符不符合這份規格書」。
兩道關卡:存檔檢查,跟送審前檢查
為什麼要分兩道關卡?因為寫規格常常要分好幾次慢慢寫完,如果每次存檔都要求「全部填齊」,使用者寫到一半根本存不了;反過來,格式錯掉的資料(例如壞掉的 JSON)如果被存進去,後面每個讀到它的地方都會壞掉,所以格式錯誤要在存檔那一刻就擋下來,不等到送審才發現。
版本:一旦送審,內容就凍結
草稿跟被退回的版本可以隨意修改,但只要進入「已送審」「已發布」「已下架」任何一種狀態,內容就不能再修改——要改規格,就要按「建立新版本」,系統會複製上一版的內容成為新的草稿。這是因為已發布的版本可能已經有會員拿到使用權、正在被 AI 呼叫,如果內容可以原地被偷改,等於繞過了審核流程把呼叫導去別的地方。同一支服務同時也只能有一個草稿或審核中的版本,避免兩份草稿互相打架。
上游密鑰:只寫得進去、讀不出來
有些上游服務需要帶密鑰才能呼叫。這類憑證資料跟公開規格分開存放,而且遵守三個原則:①存進資料庫前先加密,就算整個資料庫被偷走,沒有對應的加解密金鑰也解不開;②只寫不讀——設定好之後,任何頁面都不會再顯示密鑰的實際內容,只會顯示「已設定:某某標頭」;③公開目錄的查詢完全不去碰這張憑證資料表,只有第 8 章的安全閘道在真正要呼叫上游的那一刻才會解密使用。
老師示範做了什麼
示範情境:一位會員登記一支新的「郵遞區號查詢」服務。先故意填錯格式,看存檔怎麼被擋下;再存一份不完整的草稿,看送審前檢查列出哪些項目沒過;補齊之後全部通過。最後切換身分證明別人動不了這份草稿,並確認密鑰明文不會出現在任何頁面上。
老師逐一把缺項補齊——用途說明補到 10 字以上、網址換成加密連線、填好輸出規格與範例、設定好密鑰——原本 6 項檢查只過 1 項,補齊後全部 6 項通過。接著切換到另一位會員身分,發現對方的草稿編輯頁跟密鑰設定頁通通回傳「找不到」,證明別人的草稿真的動不了。
自己動手的步驟
步驟一:擴充版本欄位
幫版本資料表多加兩個欄位:認證方式、請求範例。既有的資料在升級資料庫結構時,要記得手動指定一個合理的預設值(例如「不需認證」、空物件 {}),不能讓既有資料因為升級結構而變成無法讀取的壞資料。
步驟二:JSON Schema 驗證器
包裝一個規格驗證工具,提供兩個能力:「這份規格書本身合法嗎」(用官方的「規格書的規格書」去檢查)跟「這份資料符不符合這份規格書」,兩者都只回傳簡單易懂的錯誤訊息(把一堆巢狀的包裝錯誤過濾掉,只留最底層真正有意義的那幾條)。
步驟三:草稿服務——只能改自己的、送審後不能改
修改草稿的規則最多:先確認這個版本屬於登入的這個人(不是就直接回「找不到」),再確認狀態必須是草稿或被退回(其他狀態一律拒絕,並提示「請建立新版本」),最後才跑存檔檢查。
// 存檔檢查(節錄想法)
若名稱或分類空白 → 錯誤
若方法不是 GET/POST → 錯誤
若網址不是合法的 http/https 完整網址、含帳密或片段 → 錯誤
若兩個 JSON Schema 驗證不合法 → 錯誤
若請求範例不是合法 JSON → 錯誤
送審前檢查則額外要求:用途說明至少 10 字、網址要用加密連線(本機測試網址除外)、輸入規格最上層一定要是「物件」型別、輸出規格不能是空的、請求範例不能是空物件且必須符合輸入規格、如果認證方式是「密鑰」就必須已經設定憑證。
步驟四:控制器、表單與密鑰加密
修改草稿的表單送出時,第一件事就是先確認這份草稿屬不屬於登入的這個人,再看表單內容合不合格——順序不能反過來,否則會出現「越權的請求先被當成普通的表單驗證失敗處理」這種順序錯誤(雖然沒有洩漏資料,但代表檢查順序本身有問題)。密鑰加密只需要呼叫框架內建的一個加解密服務,並且給它一個專屬的用途字串,確保這組加密只用在「上游憑證」這個用途上,不會被其他用途誤用同一把鑰匙解開。
常見錯誤
| 症狀 | 原因 | 怎麼處理 |
|---|---|---|
| 用途說明留空,卻顯示英文的必填提示 | 框架對「非可為空」的文字型別會自動要求必填,訊息是英文預設值 | 明確寫上中文的必填提示訊息 |
| 規格書驗證回報兩個看起來很像的錯誤 | 型別名稱拼錯了,而後設規格允許的固定名稱有好幾種,兩種都不符合所以各報一次 | 換成正確的固定型別名稱(例如「物件」「文字」「整數」等) |
| 存檔時整頁出現例外錯誤 | 表單欄位被自動轉換成空值,但驗證程式沒有先做防禦性處理 | 把可能是空值的欄位在讀取時先補成空字串再驗證 |
怎麼驗收+反向驗證
- 缺少必要資訊就不能送審:打開一份不完整的草稿,送審前檢查至少有幾項沒通過,畫面明確提示不能送審;補齊之後重新整理,全部項目變成通過。
- 只能修改自己的草稿:用另一位會員身分,對別人的草稿做讀取、修改、設定密鑰的操作,三者都必須得到「找不到」。
- 密鑰不會出現在公開目錄:設定好密鑰內容後,逐一檢查前臺目錄、詳細頁、後臺管理列表,甚至提供者自己的頁面,都不能包含密鑰的原文;未發布版本的公開詳細頁應該回「找不到」。
- 反向驗證:對已經送審的版本嘗試送出修改,必須被拒絕,而且資料庫裡的內容不能有任何改變。