关于接口设计,需要注意区分**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