// 过期验证
if (microtime(true)*1000 - $_REQUEST['timestamp'] > 5000) {
throw new \Exception(401, 'Expired request');
}
// 签名验证(公钥校验省略)
$params = ksort($_REQUEST);
unset($params['sign']);
$sign = md5(sha1(implode('-', $params) . $_REQUEST['app_key']));
if ($sign !== $_REQUEST['sign']) {
throw new \Exception(401, 'Invalid sign');
}
/**
* 重放攻击
* @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');
}
// 限流
$key = md5("{$_REQUEST['REQUEST_URI']}-{$_REQUEST['REMOTE_ADDR']}-{$_REQUEST['did']}");
if ($redisInstance->get($key) > 60) {
throw new \Exception(401, 'Request limit');
}
$redisInstance->incre($key);
// 转义
$username = htmlspecialchars($_REQUEST['username']);
/**
* 检验抽象类
*/
abstract class Check
{
/**
* 下一个check实体
*
* @var object
*/
private $nextCheckInstance;
/**
* 校验方法
*
* @param Request $request 请求对象
*/
abstract public function operate(Request $request);
/**
* 设置责任链上的下一个对象
*
* @param Check $check
*/
public function setNext(Check $check)
{
$this->nextCheckInstance = $check;
return $check;
}
/**
* 启动
*
* @param Request $request 请求对象
*/
public function start(Request $request)
{
$this->doCheck($request);
// 调用下一个对象
if (! empty($this->nextCheckInstance)) {
$this->nextCheckInstance->start($request);
}
}
}
// 校验公共参数类
class ParamsCheck extends Check
{
public function operate()
{
// 校验公共参数
# code ...
}
}
// 校验签名类
class SignCheck extends Check
{
public function operate()
{
// 校验签名
# code ...
}
}
// 等等...
// 前置中间件类
class FrontMiddleware
{
public function run()
{
// 初始化一个:必传参数校验的check
$checkParams = new ParamsCheck();
// 初始化一个:签名check
$checkSign = new SignCheck();
// 初始化一个:频率check
$checkFrequent = new FrequentCheck();
// 等等...
// 构成对象链
$checkParams->setNext($checkSign)
->setNext($checkFrequent)
...
// 启动
$checkParams->start();
}
}