關于接口設計,需要注意區分**PC**,**WAP**,**APP**不同端的接口請求和通用性,以及實現**簽名鑒權**,**訪問控制**等功能。
## **公共參數**
公共參數是每個接口都要攜帶的參數,描述每個接口的基本信息,用于統計或其他用途,放在 header 或者 url 參數中
* **timestamp** 毫秒級時間戳:
1. 客戶端的請求時間標示
2. 后端可以做請求過期驗證
3. 該參數參與簽名算法增加簽名的唯一性
* **app_key/source** 簽名公鑰(來源):
簽名算法的公鑰,后端通過公鑰可以得到對應的私鑰
* **sign** 接口簽名:
通過請求的參數和定義好的算法生成接口簽名,作用防止`中間人`篡改請求參數
* **did** 設備ID:
設備的唯一標示,生成規則例如 Android 的 MAC 地址的md5和 ios 曾今 udid(目前無法獲取)的md5。
1. 數據收集
2. 便于問題追蹤
3. 消息推送標示
* version 客戶端版本
* token 登錄令牌
* os 手機系統版本
* from 請求來源
* screen 手機尺寸
* model 機型
* net 網絡狀態
## **響應數據**
響應數據會包含三個屬性,**狀態碼(code**,**信息描述(message**,**響應數據(data)**。
~~~json
{
"code": 1,
"message": "成功",
"data": {
"list": []
}
}
~~~
## **接口安全性**
### **過期驗證**
通過時間戳進行驗證
~~~php
if (microtime(true) * 1000 - $REQUEST['timestamp'] > 5000) {
throw new \Exception(401, 'Expired request');
}
~~~
### **簽名驗證(公鑰效驗省略,如果是 saas,密鑰可能不同)**
通過配對私鑰的加密算法產生簽名,請求中攜帶簽名進行鑒權。
~~~php
$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 服務器
~~~php
/**
@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 服務器
~~~php
$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 攻擊
~~~php
$username = htmlspecialchars($_REQUEST['username']);
~~~
## **接口的解耦設計**
1. 活用中間件、鉤子。
2. 借口多用 POST請求,少用 get
3. 廢棄的代碼及時刪除,或者注釋并標注
4. 接口文件合理切割(laravel,lumen等有接口文件的框架)
5. 服務間調用不要私鑰公鑰相同,免得一破百破
## **接口的狀態碼**
~~~
200 -> 正常
400 -> 缺少公共必傳參數或者業務必傳參數
401 -> 接口校驗失敗 例如簽名
403 -> 沒有該接口的訪問權限
499 -> 上游服務響應時間超過接口設置的超時時間
500 -> 代碼錯誤
501 -> 不支持的接口method
502 -> 上游服務返回的數據格式不正確
503 -> 上游服務超時
504 -> 上游服務不可用
~~~
- PHP
- PHP 核心架構
- PHP 生命周期
- PHP-FPM 詳解
- PHP-FPM 配置優化
- PHP 命名空間和自動加載
- PHP 運行模式
- PHP 的 Buffer(緩沖區)
- php.ini 配置文件參數優化
- 常見面試題
- 常用函數
- 幾種排序算法
- PHP - 框架
- Laravel
- Laravel 生命周期
- ThinkPHP
- MySQL
- 常見問題
- MySQL 索引
- 事務
- 鎖機制
- Explain 使用分析
- MySQL 高性能優化規范
- UNION 與 UNION ALL
- MySQL報錯:sql_mode=only_full_group_by
- MySQL 默認的 sql_mode 詳解
- 正則表達式
- Redis
- Redis 知識
- 持久化
- 主從復制、哨兵、集群
- Redis 緩存擊穿、穿透、雪崩
- Redis 分布式鎖
- RedisBloom
- 網絡
- 計算機網絡模型
- TCP
- UDP
- HTTP
- HTTPS
- WebSocket
- 常見幾種網絡攻擊方式
- Nginx
- 狀態碼
- 配置文件
- Nginx 代理+負載均衡
- Nginx 緩存
- Nginx 優化
- Nginx 配置 SSL 證書
- Linux
- 常用命令
- Vim 常用操作命令
- Supervisor 進程管理
- CentOS與Ubuntu系統區別
- Java
- 消息隊列
- 運維
- RAID 磁盤陣列
- 邏輯分區管理 LVM
- 業務
- 標準通信接口設計
- 業務邏輯開發套路的三板斧
- 微信小程序登錄流程
- 7種Web實時消息推送方案
- 用戶簽到
- 用戶注冊-短信驗證碼
- SQLServer 刪除同一天用戶重復簽到
- 軟件研發完整流程
- 前端
- Redux
- 其他
- 百度云盤大文件下載
- 日常報錯記錄
- GIT
- SSL certificate problem: unable to get local issuer certificate
- NPM
- reason: connect ECONNREFUSED 127.0.0.1:31181
- SVN
- SVN客戶端無法連接SVN服務器,主機積極拒絕
- Python
- 基礎
- pyecharts圖表
- 對象
- 數據庫
- PySpark
- 多線程
- 正則
- Hadoop
- 概述
- HDFS