请求方 使用
ApiAuthService::buildUrl($domain, ['terminal' => 1, 'ts' => time()]);
//http://域名/adminapi/login/platformLogin?sign=F7FE8A150DEC18BE8A71C5059742C81A&terminal=1&ts=1736904841
接收方
$getParams = $this->request->get();
$validate = ApiAuthService::check($getParams);
if (!$validate) {
return $this->fail('签名验证失败');
}
<?php
namespace app\adminapi\service;
/**
* 服务
*/
class ApiAuthService
{
const SECRET = '加密KEY';
/**
* 验证请求的合法性
*
* 该方法主要用于验证来自第三方的请求是否合法通过对比请求参数中的签名和服务器生成的签名是否一致
* 同时,它还会检查请求的时间戳以确保请求在允许的时间范围内发出,以防止过期请求被接受
*
* @param array $params 包含请求参数的数组,应包括签名(sign)和时间戳(ts)
* @return bool 如果签名验证通过且时间戳在有效范围内,则返回true;否则返回false
* @author Harvey
* @date 2025/1/14 11:23
*/
public static function check($params)
{
// 提取签名
$sign = $params['sign'] ?? '';
// 移除签名参数,以便在后续步骤中重新计算签名
unset($params['sign']);
// 检查参数中是否包含时间戳
if (!array_key_exists('ts', $params)) {
return false;
}
// 获取当前时间戳
$ts = time();
// 检查时间戳是否在允许的范围内(当前时间前后300秒内)
if ($ts < $params['ts'] || $ts - 300 > $params['ts']) {
return false;
}
// 使用剩余参数和密钥生成MD5签名
$md5_str = self::getSign($params, self::SECRET);
// 记录调试信息
trace('我方生成的sign值');
trace($md5_str);
// 比较生成的签名和接收到的签名是否一致
return strcmp($md5_str, $sign) == 0 ? true : false;
}
/**
* 生成签名字符串
* * - 对参数进行数组排序
* * - 将secret放到数组最前面
* * - 将数组进行url编码
* * - 将url编码后的字符串进行md5加密
* * - 将md5加密后的字符串进行大写
* @param $params
* @param $code
* @return string
* @author Harvey
* @date 2025/1/14 10:56
*/
public static function getSign($params, $code)
{
ksort($params);
$params = array_merge(['secret' => $code], $params);
$params_str = http_build_query($params);
return strtoupper(md5($params_str));
}
/**
* 构建URL
*
* 该方法用于将给定的域名、参数和密钥组合成一个带有查询字符串的URL
* 它首先将密钥添加到参数数组中,然后将所有参数转换为查询字符串格式,
* 并将其附加到域名后面
*
* @param string $url 接口,例如 'http://example.com'
* @param array $params 查询参数数组,例如 ['key1' => 'value1', 'key2' => 'value2']
* @param string $secret 默认使用类常量SECRET作为密钥,可以通过传递不同的密钥来覆盖默认值
*
* @return string 返回构建好的完整URL,例如 'http://example.com?key1=value1&key2=value2&secret=your_secret'
*
* @author Harvey
* @date 2023-10-05 14:30:00
*/
public static function buildUrl($url, $params, $secret = self::SECRET)
{
// 将密钥与参数数组合并,确保密钥作为第一个参数
$sign = self::getSign($params, $secret);
$params = array_merge(['sign' => $sign], $params);
// 将参数数组转换为查询字符串,并将其附加到域名后面
return $url . '?' . http_build_query($params);
}
/* public function test()
{
$sign = PlatformService::getSign([
'u' => 1,
'a' => 1,
'ts' => time(),
], PlatformService::SECRET);
dump($sign);
dump(PlatformService::check([
'u' => 1,
'a' => 1,
'ts' => time(),
'sign' => $sign,
]));
}*/
}