本帖最后由 riyad 于 2025-2-21 19:52 编辑
) f: F) {" S2 @4 l! n9 j1 |+ p. `7 ^
在应用启动参数 列表中,初始化数据位于 tgWebAppData 参数中。 这是一组数据,主要与启动 小应用程序的特定用户有关。 初始数据的一个显著特点是,它可用作身份验证或 授权因素。 因此,不要忘记应用程序 和初始数据的安全性。 检索要提取初始数据,开发人员可以使用 @telegram-apps/sdk 中的 retrieveLaunchParams 函数。 - import { retrieveLaunchParams } from '@telegram-apps/sdk';5 k' u5 n) V0 ]4 h$ T z$ u q2 Y
8 @( V/ B) \0 \/ h# ]4 }1 B- const { initDataRaw, initData } = retrieveLaunchParams();
复制代码 授权和认证初始化数据的一个特点是可以用作授权或 身份验证的因素。 事实上,原生 Telegram 应用程序生成的数据会使用 Telegram 机器人的密钥对 进行签名,然后生成的签名会放在 参数本身旁边。 因此,知道了 Telegram 机器人的秘钥,开发者就有机会验证 参数的签名,确保这些参数确实是发给指定用户的。 此外,签名验证操作足够快,不需要大量服务器 资源。 TIP 你可以在这篇文章中找到使用不同编程语言的示例。 : O! F- o* u, r2 e) c
发送至服务器为了在服务器上对用户进行授权,开发者需要传输启动小程序时指定的初始化 数据。 开发人员可以在每次向服务器发送请求时传输这些信息,然后在服务器端进行签名验证 。 下面是开发人员向服务器发送初始数据的方法: - import { retrieveLaunchParams } from '@telegram-apps/sdk';
. S* |2 c2 E! y' y. A' Y) ~& q - , W5 d) r/ b" ` v. q+ ?
- const { initDataRaw } = retrieveLaunchParams();" g) D( b# r2 v; E- w9 A! y
0 U/ \: o, _& |: V0 T- Z6 d- fetch('https://example.com/api', {
3 d: w* q( }/ k9 [ - method: 'POST',
6 G5 E2 K3 A3 y1 ` - headers: {
: u" x. }; ~3 g4 q/ V - Authorization: `tma ${initDataRaw}`
/ M2 O9 c5 U) k5 }# _3 k - }," Z1 F" I) E3 g' ?3 f- d4 F
- });
复制代码反过来,服务器端必须执行以下操作: - 获取 Authorization(授权)标头的值;
- 检查其第一部分是否等于 tma;
- 获取初始数据并 验证 其签名。2 |/ z. Z6 i* X7 W" S1 b
如果该算法成功,应用程序的服务器部分就可以信任传输的 初始数据。 验证初始数据验证是客户端和服务器之间通信 中最重要的部分之一。 它的有效性保证了初始数据可以被信任 并在未来的代码执行中使用。 要知道,初始数据是以查询参数列表的形式呈现的,要验证 ,开发人员应遵循以下步骤: - 遍历所有键值对,并以 格式创建字符串值数组 {key}={value}。 hash 应排除在外,但要记下来。 代表初始数据符号,将用于验证过程的最后一步。
- 将计算出的数组按字母顺序排序。
- 使用密钥 WebAppData 创建 HMAC-SHA256,并将其应用于绑定到迷你应用程序的 Telegram Bot 令牌。
- 使用第 3 步的结果作为密钥创建 HMAC-SHA256。 将 应用于第 2 步 中收到的带换行符(\n)的成对数组,并将结果显示为十六进制符号序列。
- 将第 1 步收到的 hash 值与第 4 步的结果进行比较。
- 如果这些值相等,则传递的初始数据是可信的。
2 M8 F' o U( O2 U8 j, \. `
N9 u" K; S( O; {. a( }5 TTIP 在实际应用中,建议使用其他机制来验证 初始化数据。 例如,添加到期日期。 这种检查可以通过 auth_date参数来实现,该参数负责参数创建的日期。 该 解决方案可在初始化数据被盗的情况下,防止 攻击者不断使用这些数据。 TIP 为避免初始数据验证过程中可能出现的问题,我们建议使用 成熟且经过 测试的软件包: 2 O9 V4 o" F- E0 L: \2 d! I
示例让我们想象一下,我们有这样的输入: - Telegram Bot token:( x* Q m; r+ n# |
- 5768337691:AAGDAe6rjxu1cUgxK4BizYi--Utc3J9v5AU$ v, g& x) v9 d1 l
- + H( ^5 z- @# @) g
- Init data:5 P" u7 C1 J7 M! p1 C; t! I
- user=%7B%22id%22%3A279058397%2C%22first_name%22%3A%22Vladislav%22%2C%22last_name%22%3A%22Kibenko%22%2C%22username%22%3A%22vdkfrost%22%2C%22language_code%22%3A%22en%22%2C%22is_premium%22%3Atrue%2C%22allows_write_to_pm%22%3Atrue%7D2 w! i$ X, l% F) `1 {& |: }
- &chat_instance=-3788475317572404878
, h3 \9 ^ i$ w# @9 @ - &chat_type=private+ r6 q0 j$ H& v) h' K& L0 D& x- U
- &auth_date=1709144340
% |0 ~: u. q% e3 ~ - &hash=371697738012ebd26a111ace4aff23ee265596cd64026c8c3677956a85ca1827
复制代码 完成第 1 步和第 2 步后,我们将收到以下数据:
$ }, r& G, ~7 u0 a# A4 `
& S6 l0 X/ ?' p- // Sorted pairs.
1 g/ `; ] E, j& x - [
' `6 }" e" `) u2 \ ~ - 'auth_date=1709144340',% ~ ~( x7 y5 _7 E* `0 e( h2 D2 H
- 'chat_instance=-3788475317572404878',
& G w1 m9 H0 I2 {% B- Z - 'chat_type=private',
1 {# G5 \3 W2 y b! f* u8 z7 G - 'user={"id":279058397,"first_name":"Vladislav","last_name":"Kibenko","username":"vdkfrost","language_code":"en","is_premium":true,"allows_write_to_pm":true}'- x X, P( k- q( I/ V
- ]3 L$ u" F- Y* ~% U
- - h1 C6 }) X' |+ j
- // Hash.; V3 H' I9 w" s/ X" f2 A
- '371697738012ebd26a111ace4aff23ee265596cd64026c8c3677956a85ca1827'
复制代码 然后,创建第 3 步所需的 HMAC-SHA256。 它应基于 WebAppData 字面字符串值和 Telegram Bot token。2 }' Q' ?% g# U4 r/ X* _& g1 {
- HMAC-SHA256(
* X! u( ?" U& a - "WebAppData", % E. N! m, I% ^& h/ \
- "5768337691:AAGDAe6rjxu1cUgxK4BizYi--Utc3J9v5AU"
3 M( {* M( Z6 x9 w e0 E8 Z - ) = "aa492a44bdf019c759defb1698c1d77690189973945491a756051cdc1207a449"
复制代码 最后,让我们使用 第 2 步收到的排序对和第 3 步的值来计算初始数据符号:- j N6 d+ X$ }+ a" k
- joined_pairs =
5 T( R! K$ o6 f$ J - "auth_date=1709144340% H/ }# `! A$ T9 H
- chat_instance=-3788475317572404878
; E# A! M( z0 w - chat_type=private2 m) n1 K' g; d/ Z. C3 b$ T
- user={"id":279058397,"first_name":"Vladislav","last_name":"Kibenko","username":"vdkfrost","language_code":"en","is_premium":true,"allows_write_to_pm":true}"
$ e' ]( ~$ L: Y) K0 a6 a
; k& ?3 x+ M; @ Y+ K( ]$ c- HMAC-SHA256(
2 D9 \# z$ M4 U O/ V( y - "aa492a44bdf019c759defb1698c1d77690189973945491a756051cdc1207a449",
) z, l9 K5 W+ n6 y5 m- l" x' X. V* ^. Q - joined_pairs,
! p& O& e# P$ y6 ? - ) = "371697738012ebd26a111ace4aff23ee265596cd64026c8c3677956a85ca1827"
复制代码 现在,将最后收到的结果与第 1 步中的 hash 值进行比较,我们可以看到它们是相等的。 这意味着,我们可以信任传递的初始数据。3 c4 d2 _6 i5 A4 G
& p3 y$ W, Q- N
可以查看参数列表 。
: u) }" J# Z. h# D3 r. ~5 {5 `! H3 P9 X; g
|