提示:通用接口设计参数,验签等
一、接口签名设计
公共参数:
公共参数 | 含义 | 意义 |
---|---|---|
timestamp | 时间戳 | 请求时间,做请求过期验证 |
sign | 签名 | 请求参数,通过一定算法生成签名 |
source | 来源 | 判断请求来源(Android,ios,wx,miniprogram,web等) |
noise | 随机字符串 | 做请求唯一标识 |
app_key | 公钥 | 通过公钥查找私钥,(可以根据不同的source提供不同的私钥,也可以双方约定固定一个私钥) |
version | 版本号 | 可有可无(报错时候方便排查是否是用户未升级) |
以下示例为PHP代码
生成签名方式:
/**
* 生成签名
*/
public static function MakeSign($datas, $appsecret = null, $emptyvalue = false)
{
//签名步骤一:按字典序排序参数
ksort($datas);
$string = self::ToUrlParams($emptyvalue);
//签名步骤二:在string后加入KEY
$string = $string . "&key=" . $appsecret;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
}
/**
* 格式化参数格式化成url参数
*/
public static function ToUrlParams($datas)
{
$buff = "";
foreach ($datas as $k => $v) {
if (strtolower($k) != "sign" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
- 过期验证
//请求1分钟之内有效
if (time() - $_POST['timestamp'] > 60) {
throw new Exception('Expired request');
}
- 重复攻击
//利用redis,同样的请求只允许请求一次
$key = md5("{$_POST['timestamp']}-{$_POST['noise']}-{$_POST['source']}");
if ($redisInstance->exists($key)) {
throw new Exception( 'Repeated request');
}
- 限流
对请求ip限流;
对请求接口限流;
对请求用户限流;
//利用redis 对请求ip限流
$key = md5("$_POST['REMOTE_ADDR']");
if ($redisInstance->get($key) > 60) {
throw new Exception('Request limit');
}
$redisInstance->incre($key);
二、接口注意事项
- 敏感信息加密,用户登录密码,身份证号,银行卡号等;
- 请求IP加白名单,(不适用于C端项目);
- 参数校验:是否必填,字段类型,字段长度,枚举值,转义:htmlspecialchars($_POST[‘name’]);
- 记录请求日志,最好有traceId,串联整个请求日志,尤其是分布式日志;
- 接口幂等设计,短时间内,接口被调用多次返回相同的结果:可以利用redis,数据库唯一索引,数据库锁等实现;
- 批量查询,限制查询条数,最多500条;
- 接口压测:测试并发和限流等是否生效;
- 异步处理:利用中间件MQ,接口返回ok,业务在队列中稍后处理;
- 数据脱敏:返回的手机号,身份证号做脱敏处理;
- 对于一些验证码接口,可以做图形验证。做预警,判断每日每周短信发送量增长值,防止盗刷;
- 统一封装异常,防止数据库,代码行数等报错信息被用户看到;
- 废弃代码删掉,比如一些活动页,获取验证码的接口,可以在设计初期就提前限制时间,活动完之后删掉废弃代码;