讨论数量:
AES 加密 肯定是没有加上时间戳的校验
// 生成签名
protected function generateUserApplySign($headers, $secretKey): string
{
// 移除 Api-Sign 字段
if (isset($headers['Api-Sign'])) {
unset($headers['Api-Sign']);
}
ksort($headers);
$buff = '';
foreach ($headers as $k => $v) {
if ($v != "" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
// 去除最后一个&
$string = trim($buff, "&");
// 在string后加入KEY
$string = $string . "&key=" . $secretKey;
// sha256加密
$string = hash_hmac('SHA256', $string, $secretKey);
// 所有字符转为大写
return strtoupper($string);
}
/**
* 签名验证
* @param Request $request
* @return bool
* @throws InvalidRequestException
*/
protected function verifyUserApplySign(Request $request): bool
{
$requiredHeaders = ['Api-Appid', 'Api-Nonce-Str', 'Api-Timestamp', 'Api-Sign'];
foreach ($requiredHeaders as $header) {
if (!$request->headers->has($header)) {
throw new InvalidRequestException($header . ' 不能为空');
}
}
// 判断 Api-Appid 是否正确
$userApplySecret = UserApplySecret::query()->where('app_id', $request->headers->get('Api-Appid'))->first();
if (!$userApplySecret) {
throw new InvalidRequestException('Api-Appid 不存在');
}
if (!$userApplySecret['is_valid']) {
throw new InvalidRequestException('Api-Appid 已失效');
}
// 判断是否过期
if (Carbon::now()->gt($userApplySecret['valid_at'])) {
throw new InvalidRequestException('Api-Appid 已过期');
}
// 判断请求次数是否超限
if ($userApplySecret['request_count'] >= $userApplySecret['available_count']) {
throw new InvalidRequestException('Api-Appid 请求次数已超限');
}
$headers = [
'Api-Appid' => $request->headers->get('Api-Appid'),
'Api-Nonce-Str' => $request->headers->get('Api-Nonce-Str'),
'Api-Timestamp' => $request->headers->get('Api-Timestamp'),
'Api-Sign' => $request->headers->get('Api-Sign'),
];
if ($userApplySecret['time_out'] && !$this->allowTimestamp($headers['Api-Timestamp'], $userApplySecret['time_out'])) {
throw new InvalidRequestException('Api-Timestamp 超时');
}
// 生成签名
$sign = $this->generateUserApplySign($headers, $userApplySecret['secret_key']);
Log::info('Api-User-Sign: ', ['generateUserApplySign' => $sign, 'Api-User-Sign' => $headers['Api-Sign']]);
if (!hash_equals($sign, $headers['Api-Sign'])) {
throw new InvalidRequestException('Api-Sign 不正确');
}
// 请求成功, 记录请求次数
$userApplySecret->increment('request_count');
return true;
}
推荐文章: