当前位置: 首页 > news >正文

手机号+平台ID和appsecret的简单签名算法

一个基于手机号、平台ID和appsecret的简单签名算法的PHP实现,包含签名生成和验证的完整设计思路

首先,我们设计一个简单且安全的签名流程,核心步骤和参数如下:

步骤关键参数/操作说明
1. 参数排序ksort($params)确保参数顺序一致
2. 构造待签名字符串手机号平台ID随机数(Nonce)时间戳包含身份、时效性和唯一性要素
3. 生成签名hash_hmac (使用SHA-256)利用密钥生成不可伪造的签名
4. 验证签名重新计算并比对签名、检查时间戳和随机数服务端验证请求的合法性

PHP代码实现

1. 签名生成类 (SignatureGenerator)

这个类用于在客户端或调用方生成签名。

<?phpclass SignatureGenerator
{private $appSecret;public function __construct($appSecret){$this->appSecret = $appSecret;}/*** 生成签名* @param string $appId 平台ID* @param string $phone 手机号* @param int $timestamp 时间戳(秒)* @param string $nonce 随机字符串* @return string 返回Base64编码的签名*/public function generateSignature($appId, $phone, $timestamp, $nonce){// 1. 准备待签名参数(排除sign本身)$params = ['appid' => $appId,'phone' => $phone,'timestamp' => $timestamp,'nonce' => $nonce];// 2. 按参数名的ASCII码字典序排序ksort($params);// 3. 拼接键值对,形成字符串A$stringA = '';foreach ($params as $key => $value) {// 空值参数通常不参与签名,但这里所有参数都是必需的$stringA .= $key . '=' . $value . '&';}$stringA = rtrim($stringA, '&'); // 去掉末尾的'&'// 4. 在字符串A最后拼接上AppSecret,得到待签名字符串stringSignTemp$stringSignTemp = $stringA . '&key=' . $this->appSecret;// 5. 使用HMAC-SHA256算法计算签名$hash = hash_hmac('sha256', $stringSignTemp, $this->appSecret, true);// 6. 对二进制签名进行Base64编码$signature = base64_encode($hash);return $signature;}/*** 生成带签名的完整请求参数数组*/public function generateSignedRequest($appId, $phone){$timestamp = time();$nonce = bin2hex(random_bytes(8)); // 生成16位随机字符串$signature = $this->generateSignature($appId, $phone, $timestamp, $nonce);$requestParams = ['appid' => $appId,'phone' => $phone,'timestamp' => $timestamp,'nonce' => $nonce,'sign' => $signature // 将签名加入请求参数];return $requestParams;}
}?>
2. 签名验证类 (SignatureVerifier)

这个类用于在服务端验证收到的请求签名是否合法。

<?phpclass SignatureVerifier
{private $appSecret;private $timestampTolerance = 300; // 时间戳容差,默认5分钟(300秒)public function __construct($appSecret){$this->appSecret = $appSecret;}/*** 验证签名* @param array $requestParams 收到的所有请求参数(必须包含appid, phone, timestamp, nonce, sign)* @return bool 验证通过返回true,失败返回false*/public function verifySignature($requestParams){// 1. 检查必要参数是否存在if (!isset($requestParams['appid'], $requestParams['phone'], $requestParams['timestamp'], $requestParams['nonce'], $requestParams['sign'])) {return false;}$incomingSignature = $requestParams['sign'];// 从参数中移除签名,因为签名本身不参与签名计算unset($requestParams['sign']);// 2. 验证时间戳有效性(防止重放攻击)$currentTime = time();$requestTime = $requestParams['timestamp'];if (abs($currentTime - $requestTime) > $this->timestampTolerance) {return false; // 请求已过期}// 3. (可选但推荐)检查Nonce唯一性,防止重复请求// 通常需要借助缓存(如Redis)记录近期使用过的nonce// 此处简化示例,实际生产环境需要实现// if ($this->isNonceUsed($requestParams['nonce'])) { return false; }// 4. 根据收到的参数重新计算签名$generator = new SignatureGenerator($this->appSecret);$calculatedSignature = $generator->generateSignature($requestParams['appid'],$requestParams['phone'],$requestParams['timestamp'],$requestParams['nonce']);// 5. 使用hash_equals防止时序攻击,比较计算出的签名和收到的签名是否一致return hash_equals($calculatedSignature, $incomingSignature);}/*** 设置时间戳容差(秒)*/public function setTimestampTolerance($tolerance){$this->timestampTolerance = $tolerance;}// 示例方法:检查nonce是否已被使用(需结合缓存系统如Redis实现)// private function isNonceUsed($nonce) {//     // 伪代码:检查这个nonce在缓存中是否存在,若存在则返回true(已使用)//     // 若不存在,则将其存入缓存并设置过期时间(例如5分钟),然后返回false// }
}?>
3. 完整使用示例

下面的代码演示了如何在实际的API调用和接收中使用上述类。

<?php// ==================== 调用方(客户端) ====================
// 假设双方共享的密钥,需要严格保密
$sharedAppSecret = "YourSuperSecretKey123!";// 1. 实例化签名生成器
$signatureGenerator = new SignatureGenerator($sharedAppSecret);// 2. 业务参数
$appId = "100001"; // 平台ID
$userPhone = "13800138000"; // 用户手机号// 3. 生成带签名的请求参数数组
$signedRequestData = $signatureGenerator->generateSignedRequest($appId, $userPhone);echo "生成的请求参数(可用于HTTP GET/POST请求):\n";
print_r($signedRequestData);
// 输出类似:
// Array
// (
//     [appid] => 100001
//     [phone] => 13800138000
//     [timestamp] => 1728835200
//     [nonce] => 5a8f1e9d4c7b2a61
//     [sign] => abc123...Base64编码的签名...
// )// 可以将 $signedRequestData 作为参数发起HTTP请求
// 例如: http://api.example.com/service?appid=100001&phone=13800138000&timestamp=1728835200&nonce=5a8f1e9d4c7b2a61&sign=abc123...// ==================== 服务端 ====================
// 1. 实例化签名验证器(使用相同的密钥)
$signatureVerifier = new SignatureVerifier($sharedAppSecret);// 2. 模拟接收到的请求数据(通常是 $_GET 或 $_POST)
$receivedRequestData = $signedRequestData; // 这里直接用上面生成的数据模拟// 3. 进行签名验证
$isValid = $signatureVerifier->verifySignature($receivedRequestData);if ($isValid) {echo "✓ 签名验证成功,请求合法,处理业务逻辑...\n";// ... 这里执行您的业务代码 ...
} else {echo "✗ 签名验证失败,请求可能被篡改或已过期,拒绝处理。\n";http_response_code(401); // 返回未授权状态码
}?>

关键要点说明

  1. 安全性

    • 密钥管理AppSecret 是核心机密,应妥善保管,切勿在客户端或网络中明文传输。建议使用环境变量或安全的配置中心存储。
    • 算法选择:使用 SHA-256 等强哈希算法,比 MD5 更安全。
    • 防重放攻击:通过 时间戳随机数 (Nonce) 机制有效防止请求被重复使用。
    • 签名比较:使用 hash_equals 进行比较,以避免时序攻击。
  2. 参数处理

    • 参数排序:必须严格按照字典序排序,确保服务端和客户端计算签名时参数的顺序一致。
    • 参数编码:注意参数值的原始格式,通常使用原始值进行签名计算,而不是URL编码后的值。如果进行HTTP请求,在生成签名后需要对整个请求URL(包括签名参数)进行编码。
http://www.dtcms.com/a/479516.html

相关文章:

  • 跨平台 移动网站开发安徽建工集团网站
  • 做网站需要注意什么问题工程建设公司网站
  • 《Muduo网络库:实现EventLoop事件循环》
  • 企业网站推荐微信公众号人工服务电话
  • 国家电网智能车载终端TBOX
  • 南宁网站建设升上去proxy网站
  • chatgpt-codex使用显示Error starting conversation
  • 搜狐网站建设的建议网站开发工资多少
  • Java中关于HashMap的元素遍历的顺序问题
  • 南通江苏网站建设建设淘宝网站的市场分析
  • 网站备案容易通过吗深入挖掘wordpress
  • 网站程序基础wordpress安装无法连接数据库
  • 淘宝天猫优惠卷网站建设网站建设 好发信息网
  • 柔性制造的终极答案:富唯智能机器人如何以“全能感官”实现一机多能
  • Zabbix 配置钉钉告警
  • 网站建设最快多长时间苏州做网站公司精选苏州聚尚网络
  • Docker 镜像版本Alpine、Slim、Bookworm、Bullseye、Stretch、Jessie
  • 网上网站代码可以下载吗转移网站如何转数据库
  • 企业网站示例网站建设方案撰写
  • 数据结构:哈希基础、6种哈希函数构造方法、4种解决哈希冲突的方法和哈希扩展(一致性哈希+虚拟节点+布隆过滤器)
  • 网站做哪种推广好建设银行租房网站湖北
  • 网站建设公司基本流程无锡专业做网站
  • 工商注册网站官网网站和app可以做充值余额功能
  • 东莞网站开发后缀微营销论文
  • 【AI论文】Paper2Video:从科学论文自动生成视频
  • Pod的进阶
  • 汽车4s店网站建设方案自己设计建房子的软件
  • 玉器哪家网站做的好中小企业信息网官网
  • Node.js zlib模块所有 API 详解 + 常用 API + 使用场景
  • wordpress怎么加入站长统计聊城网站建设策划建设公司