答面試官問:如何設計API介面

Martist發表於2020-09-20

關於介面設計,需要注意區分pc,wap,app不同端的介面請求和通用性,以及實現簽名鑑權,訪問控制等功能。

介面引數定義

介面設計中往可以抽象出一些新的公共引數,從事了近三年的介面開發工作中,我目前能想到了一些較為常見的公共介面引數如下:

公共引數 含意 定義該引數的意義
timestamp 毫秒級時間戳 1.客戶端的請求時間標示 2.後端可以做請求過期驗證 3.該引數參與簽名演算法增加簽名的唯一性
app_key/source 簽名公鑰(來源) 簽名演算法的公鑰,後端通過公鑰可以得到對應的私鑰(也就是來源的意義)
sign 介面簽名 通過請求的引數和定義好的簽名演算法生成介面簽名,作用防止中間人篡改請求引數
did 裝置 ID 裝置的唯一標示,生成規則例如android的mac地址的md5和ios曾今udid(目前無法獲取)的md5, 1:資料收集 2.便於問題追蹤 3.訊息推送標示

介面版本化

我不太習慣把版本號直接放到路由裡面去,還有其他方式可以區別版本,比如get、post傳參。

介面安全性

過期驗證

通過時間戳進行驗證

if (microtime(true)*1000 - $_REQUEST['timestamp'] > 5000) {

throw new \Exception(401, 'Expired request');

}

簽名驗證(公鑰校驗省略,如果是saas,金鑰可能不同)

通過配對私鑰的加密演算法產生簽名,請求中攜帶簽名進行鑑權。

$params = ksort($_REQUEST);

unset($params['sign']);

$sign = md5(sha1(implode('-', $params) . $_REQUEST['app_key']));

if ($sign !== $_REQUEST['sign']) {

throw new \Exception(401, 'Invalid sign');

}

重放攻擊

防止一次相同請求多次攻擊API伺服器。

/**

@params noise string 隨機字串或隨機正整數,與 Timestamp 聯合起來, 用於防止重放攻擊 例如騰訊雲是6位隨機正整數

*/

$key = md5("{$_REQUEST['REQUEST_URI']}-{$_REQUEST['timestamp']}-{$_REQUEST['noise']}-{$_REQUEST['did']}");

if ($redisInstance->exists($key)) {

throw new \Exception(401, 'Repeated request');

}

限流

防止同一ip頻繁訪問API伺服器。

$key = md5("{$_REQUEST['REQUEST_URI']}-{$_REQUEST['REMOTE_ADDR']}-{$_REQUEST['did']}");

if ($redisInstance->get($key) > 60) {

throw new \Exception(401, 'Request limit');

}

$redisInstance->incre($key);

轉義

防止注入,xss等攻擊。

$username = htmlspecialchars($_REQUEST['username']);

介面的解耦設計

  1. 活用中介軟體、鉤子

  2. 藉口多用post請求,少用get

  3. 廢棄的程式碼及時刪掉,或者註釋掉並且標註

  4. 介面檔案合理切割(laravel,lumen等有介面檔案的框架)

  5. 服務間呼叫不要私鑰公鑰相同,免得一破百破

介面的狀態碼

推薦一些公用的,如果還有私信,廣播,商城等狀態碼可以另加。

200 -> 正常

400 -> 缺少公共必傳引數或者業務必傳引數

401 -> 介面校驗失敗 例如簽名

403 -> 沒有該介面的訪問許可權

499 -> 上游服務響應時間超過介面設定的超時時間

500 -> 程式碼錯誤

501 -> 不支援的介面method

502 -> 上游服務返回的資料格式不正確

503 -> 上游服務超時

504 -> 上游服務不可用

引用自我的電子書

PHPer面試-2020

本作品採用《CC 協議》,轉載必須註明作者和本文連結
是非之外有一座花園,我們會在那裡相遇

相關文章