關於介面設計,需要注意區分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']);
介面的解耦設計
活用中介軟體、鉤子
藉口多用post請求,少用get
廢棄的程式碼及時刪掉,或者註釋掉並且標註
介面檔案合理切割(laravel,lumen等有介面檔案的框架)
服務間呼叫不要私鑰公鑰相同,免得一破百破
介面的狀態碼
推薦一些公用的,如果還有私信,廣播,商城等狀態碼可以另加。
200 -> 正常
400 -> 缺少公共必傳引數或者業務必傳引數
401 -> 介面校驗失敗 例如簽名
403 -> 沒有該介面的訪問許可權
499 -> 上游服務響應時間超過介面設定的超時時間
500 -> 程式碼錯誤
501 -> 不支援的介面method
502 -> 上游服務返回的資料格式不正確
503 -> 上游服務超時
504 -> 上游服務不可用
引用自我的電子書
本作品採用《CC 協議》,轉載必須註明作者和本文連結