新舊 API 驗證對照
這份文件用來 trace API migration 時的身份來源:request 帶什麼、舊專案呼叫哪個 method、新專案要對到哪個 method。
Header 與身份來源
| 來源 | 對應資料 | 代表意義 | 注意 |
|---|---|---|---|
X-PRO360-Rest-Api-Key | api_keys.name | client / app 合法性 | 不是 user identity。只代表呼叫端 key 有效。 |
X-PRO360-User-Session-Token | api_sessions.id | 登入 session | 通過後才解析出 users.id。 |
pro360_u_s_token cookie | api_sessions.id | web 登入 session | 新舊專案都會優先用 cookie,再看 header。 |
X-PRO360-User-Id | request internal param | 驗證後寫入的 user id | 不要信任外部傳入;只能信任驗證 method 寫入的值。 |
API key 是明碼放在 header,但實務上靠 HTTPS 傳輸。它的用途是限制合法 client、判斷平台、記錄來源與擋掉未授權呼叫;它不能取代 user session。
舊專案:get-lancer-php56
| 需求 | 常見 method | 行為 |
|---|---|---|
| API key only | RestApiHelper::hasValidApiKey($request) | 讀 X-PRO360-Rest-Api-Key,比對 active api_keys,redis cache key 是 getlancer_api_keys。 |
| 登入 session | RestApiHelper::hasValidApiSession($controller) | 先驗 API key,再用 pro360_u_s_token cookie 或 X-PRO360-User-Session-Token 查 api_sessions 與 users。 |
| 取得 user id | RestApiHelper::getUserId($request) | 讀 request->params['X-PRO360-User-Id'],同時寫 LogHelper(<url>::<method>)。這不是純 getter。 |
| ACL bypass | RestApiHelper::bypassAclFiltering($controller) | quote_requests/search_add.json、quote_services/add.json 只要 API key 有效可 bypass ACL;endpoint 內再處理 optional session / signup。 |
hasValidApiSession() 通過後會把 user id 寫進 request->params['X-PRO360-User-Id'],並更新 user access 資訊。搬移時要注意這些副作用。
新專案:pro360_api_82
| 需求 | 常見 method | 行為 |
|---|---|---|
| API key only | ApiValidation::assertApiKey($request) | API key 不合法就丟 ProcessException(ERROR_INVALID_API_KEY)。 |
| API key boolean check | ApiValidation::hasValidApiKey($request) | 回 true / false,redis cache key 是 new_api_keys。 |
| 必須登入 | ApiValidation::assertApiSession($request, $usersDO) | 先驗 API key,再查 session、user、blocked / active 狀態;通過後回 user id 並設定 request param。 |
| 可選登入 | ApiValidation::hasValidApiSession($request, $isAssertApiKey, $usersDO) | 回 true / false。$isAssertApiKey=false 時,API key 無效直接 false,不丟例外。 |
| 只取 session user id | ApiValidation::getUserIdBySessionToken($request) | 只用 session token 查 api_sessions.user_id;不等同完整 session 驗證。 |
新專案 getSessionId() 和舊專案一樣:pro360_u_s_token cookie 優先於 X-PRO360-User-Session-Token header。本地測試如果同時帶 cookie 和 header,要先確認 cookie 不是舊 user。
quote_services 系列範例
| API | 舊專案入口 / 驗證 | 新專案入口 / 驗證 | 身份規則 |
|---|---|---|---|
GET /quote_services/static_fields.json | QuoteServicesController::static_fields(),API key only | QuoteServices::static_fields(),ApiValidation::assertApiKey() | 不需要 user。 |
POST /quote_services/add.json | QuoteServicesController::add(),ACL 可被 API key bypass;內部用 RestApiHelper::hasValidApiSession() 嘗試取得登入 user | QuoteServices::add(),先 assertApiKey(),再用 hasValidApiSession(..., false) 走 optional login | API key 必要;session 可有可無。有 session 時用既有 user,無 session 時走 signup / existing user path。 |
POST /quote_services/change_status/profile_ready/{id}.json | QuoteServicesController::change_status('profile_ready', $id),RestApiHelper::hasValidApiSession() 後用 getUserId() 限定 owner | QuoteServices::change_status_profile_ready(),ApiValidation::assertApiSession() 後用 $usersDO->id 限定 owner | 必須登入,且 service 必須屬於目前 user。 |
POST /quote_services/change_status/archive/{id}.json | QuoteServicesController::change_status('archive', $id),同上 | QuoteServices::change_status_archive(),同上 | 必須登入,且 service 必須屬於目前 user。 |
GET /quote_services/external_review/link/{id}.json | QuoteServicesController::external_review(),RestApiHelper::hasValidApiSession(),失敗回 Invalid session | QuoteServices::external_review_link(),ApiValidation::hasValidApiSession(..., true),失敗回 Invalid session | 必須登入,且 service 必須屬於目前 user。 |
Migration 檢查規則
- 先判斷 endpoint 是 API key only、optional session、required session,還是 hash flow。
- 舊專案若有
RestApiHelper::getUserId(),要記錄它會寫 application log,不要當純 getter。 - 新專案 required session 對應
assertApiSession();optional session 對應hasValidApiSession(..., false)或明確說明為什麼要 assert API key。 - 驗 owner 時,不只確認 session 通過,還要確認 SQL / model 查詢有套
user_id = current user。 - 本地 curl 測試若同時帶 cookie 和 header,先清 cookie 或確認 cookie user,因為 cookie 優先。
- API key 洩漏不等於登入,但 API key only endpoint 會受影響;文件要清楚標 actor 是 client 還是 user。