如何用PHP实现Telegram WebApp Bot文档中的验证逻辑?
Telegram 数据验证的PHP正确实现方法
你的代码验证失败,核心问题是没遵循Telegram官方的字符串拼接规则和密钥生成逻辑,以下分两种常见场景给出正确实现:
场景1:Telegram Web App 用户数据验证
这是前端调用Telegram Web App后,后端验证用户数据合法性的场景:
<?php // 替换为你的机器人令牌 $bot_token = '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'; // 从请求中获取Telegram传递的参数(比如从GET的init_data解析) $init_data = $_GET; $telegram_hash = $init_data['hash']; unset($init_data['hash']); // 1. 按键名字典序升序排序参数 ksort($init_data); // 2. 拼接成「key=value」格式,用换行符连接 $data_check_string = ''; foreach ($init_data as $key => $value) { $data_check_string .= "$key=$value\n"; } // 移除最后一个多余的换行符 $data_check_string = rtrim($data_check_string, "\n"); // 3. 生成验证专用密钥 $secret_key = hash_hmac('sha256', 'WebAppData', $bot_token, true); // 4. 计算待验证的哈希值(二进制结果) $computed_hash = hash_hmac('sha256', $data_check_string, $secret_key, true); // 5. 解码Telegram返回的hash(base64url转标准base64) $telegram_hash_bin = base64_decode(strtr($telegram_hash, '-_', '+/')); // 6. 安全对比哈希(避免时序攻击) if (hash_equals($computed_hash, $telegram_hash_bin)) { echo "验证通过"; } else { echo "验证失败"; } ?>
关键注意点:
- 必须用
hash_equals()做对比,不能直接用==,防止时序攻击 - Telegram返回的
hash是base64url编码,需要替换-为+、_为/后再解码 - 参数必须严格按字典序升序排序,拼接时每个
key=value后加换行,最后一个无换行 - 验证密钥是基于
WebAppData字符串和bot token生成的HMAC结果,不是直接用bot token
场景2:Telegram Webhook 请求验证
这是后端接收Telegram推送消息时,验证请求合法性的场景:
<?php $bot_token = '你的机器人令牌'; // 如果你设置了Webhook的Secret Token,直接对比请求头即可(推荐) $secret_token = '你设置的Webhook Secret Token'; // 方式1:使用Secret Token验证(最简单) $received_secret = $_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? ''; if ($received_secret === $secret_token) { echo "验证通过"; } else { echo "验证失败"; } // 方式2:无Secret Token时,用签名验证 $received_signature = $_SERVER['HTTP_X_TELEGRAM_BOT_API_SIGNATURE'] ?? ''; if (str_starts_with($received_signature, 'sha256=')) { $received_hash = substr($received_signature, 7); $request_body = file_get_contents('php://input'); $computed_hash = hash_hmac('sha256', $request_body, $bot_token); if (hash_equals($computed_hash, $received_hash)) { echo "验证通过"; } else { echo "验证失败"; } } else { echo "验证失败"; } ?>
你之前代码的问题总结:
- 没有按Telegram要求的规则拼接待签名字符串(缺排序、缺
key=value格式、缺换行连接) - 密钥生成不符合规则(Web App场景下不是直接用bot token)
- 未正确处理Telegram返回的hash编码格式
内容的提问来源于stack exchange,提问作者Sdafs Fasafs
相关产品推荐
相关产品推荐

