本帖最后由 riyad 于 2025-2-21 19:52 编辑 / Z& Y' d3 q2 \( {' F) A1 [: c
, Q) `6 u2 ^" N
在应用启动参数 列表中,初始化数据位于 tgWebAppData 参数中。 这是一组数据,主要与启动 小应用程序的特定用户有关。 初始数据的一个显著特点是,它可用作身份验证或 授权因素。 因此,不要忘记应用程序 和初始数据的安全性。 检索要提取初始数据,开发人员可以使用 @telegram-apps/sdk 中的 retrieveLaunchParams 函数。 - import { retrieveLaunchParams } from '@telegram-apps/sdk';9 ^2 O, }( v3 Y5 v" ^" n' T
" B B! ~. t4 o) ~- const { initDataRaw, initData } = retrieveLaunchParams();
复制代码 授权和认证初始化数据的一个特点是可以用作授权或 身份验证的因素。 事实上,原生 Telegram 应用程序生成的数据会使用 Telegram 机器人的密钥对 进行签名,然后生成的签名会放在 参数本身旁边。 因此,知道了 Telegram 机器人的秘钥,开发者就有机会验证 参数的签名,确保这些参数确实是发给指定用户的。 此外,签名验证操作足够快,不需要大量服务器 资源。 TIP 你可以在这篇文章中找到使用不同编程语言的示例。
- |' v9 {& i% Q$ m! p+ a. S5 o发送至服务器为了在服务器上对用户进行授权,开发者需要传输启动小程序时指定的初始化 数据。 开发人员可以在每次向服务器发送请求时传输这些信息,然后在服务器端进行签名验证 。 下面是开发人员向服务器发送初始数据的方法: - import { retrieveLaunchParams } from '@telegram-apps/sdk';
$ P3 {' D) [, J' \5 ^3 }
) C6 t5 P7 o! c+ E- const { initDataRaw } = retrieveLaunchParams();' I% X4 H& h* D3 C& f: W
- 5 y! |% [. o2 Q- m; K" h0 S0 S+ z
- fetch('https://example.com/api', {
- M' a6 Z5 S0 \. M' ?- {( r& K - method: 'POST',, q ?( l3 R7 m
- headers: {
8 R, y" Z8 J. y2 w' m- x' q - Authorization: `tma ${initDataRaw}`8 l7 j/ F2 Q P% g
- },# M6 V+ a$ @/ U8 `- O K: y
- });
复制代码反过来,服务器端必须执行以下操作: - 获取 Authorization(授权)标头的值;
- 检查其第一部分是否等于 tma;
- 获取初始数据并 验证 其签名。( d: z7 H! Z5 \# W3 k, v. o! R
如果该算法成功,应用程序的服务器部分就可以信任传输的 初始数据。 验证初始数据验证是客户端和服务器之间通信 中最重要的部分之一。 它的有效性保证了初始数据可以被信任 并在未来的代码执行中使用。 要知道,初始数据是以查询参数列表的形式呈现的,要验证 ,开发人员应遵循以下步骤: - 遍历所有键值对,并以 格式创建字符串值数组 {key}={value}。 hash 应排除在外,但要记下来。 代表初始数据符号,将用于验证过程的最后一步。
- 将计算出的数组按字母顺序排序。
- 使用密钥 WebAppData 创建 HMAC-SHA256,并将其应用于绑定到迷你应用程序的 Telegram Bot 令牌。
- 使用第 3 步的结果作为密钥创建 HMAC-SHA256。 将 应用于第 2 步 中收到的带换行符(\n)的成对数组,并将结果显示为十六进制符号序列。
- 将第 1 步收到的 hash 值与第 4 步的结果进行比较。
- 如果这些值相等,则传递的初始数据是可信的。
9 w/ b1 n$ q; L
( L: `- _( r6 ]/ I; lTIP 在实际应用中,建议使用其他机制来验证 初始化数据。 例如,添加到期日期。 这种检查可以通过 auth_date参数来实现,该参数负责参数创建的日期。 该 解决方案可在初始化数据被盗的情况下,防止 攻击者不断使用这些数据。 TIP 为避免初始数据验证过程中可能出现的问题,我们建议使用 成熟且经过 测试的软件包: 3 W. }1 Z0 [/ u3 Z! k4 Y# S4 Z/ ~" ]
示例让我们想象一下,我们有这样的输入: - Telegram Bot token:
1 y& o" m Q: W - 5768337691:AAGDAe6rjxu1cUgxK4BizYi--Utc3J9v5AU! P9 S6 C8 H+ t @ M, c- G
- + E- r. H" X2 G, L# Z
- Init data:
; H1 k/ h" Z2 Q9 D4 p4 N' H2 e - 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%7D
) P; Z6 H, m! j0 q" [- _ - &chat_instance=-37884753175724048785 |/ V) I) S6 w- y- ]
- &chat_type=private
7 |: q& y4 W; K/ Z+ j7 v& _ - &auth_date=1709144340
5 W4 H: x [# N; Z3 j0 e) E - &hash=371697738012ebd26a111ace4aff23ee265596cd64026c8c3677956a85ca1827
复制代码 完成第 1 步和第 2 步后,我们将收到以下数据:
1 ?6 e8 [7 z2 P. Y/ [; s* Z/ o& w* Q% @; ^- D$ k$ d
- // Sorted pairs.
6 n6 ^$ L% w; h6 I5 t+ u" e; r - [
* Y7 W$ z/ U9 h- X - 'auth_date=1709144340',
- N- G: F; i" }/ L- A& M - 'chat_instance=-3788475317572404878',
+ q' f7 p8 Z9 C; f3 }( a; z - 'chat_type=private',7 e! L7 t" l% K& @ @
- 'user={"id":279058397,"first_name":"Vladislav","last_name":"Kibenko","username":"vdkfrost","language_code":"en","is_premium":true,"allows_write_to_pm":true}'! r! o& S( H2 X( t) W* y0 {4 `
- ]
% Y, ^2 f: l# g( K2 e. G
9 \1 s- f5 b( C1 ^2 |- // Hash.
2 w5 H; H$ ?4 I' {9 q1 z6 e - '371697738012ebd26a111ace4aff23ee265596cd64026c8c3677956a85ca1827'
复制代码 然后,创建第 3 步所需的 HMAC-SHA256。 它应基于 WebAppData 字面字符串值和 Telegram Bot token。
2 m/ D: t9 Y4 z3 m$ |' |3 e- HMAC-SHA256(5 W0 ]1 O7 e8 q$ b$ U; n$ Q$ V
- "WebAppData", - n8 Y- C/ x" x
- "5768337691:AAGDAe6rjxu1cUgxK4BizYi--Utc3J9v5AU"
- D6 s6 V' o/ j! P( ~$ s - ) = "aa492a44bdf019c759defb1698c1d77690189973945491a756051cdc1207a449"
复制代码 最后,让我们使用 第 2 步收到的排序对和第 3 步的值来计算初始数据符号:1 B8 a% f' Z! M& V2 d/ y& S
- joined_pairs =
8 z2 h% M$ U: s0 |# A4 m - "auth_date=17091443409 l+ }8 J5 m6 c: `& Y
- chat_instance=-3788475317572404878- g& ?$ q5 ~2 N" r* W
- chat_type=private
4 j" Y2 {, c' S! H9 i% y+ R4 o - user={"id":279058397,"first_name":"Vladislav","last_name":"Kibenko","username":"vdkfrost","language_code":"en","is_premium":true,"allows_write_to_pm":true}"9 l( n* n" e# x
- # [$ W' F- k( H: _8 ~7 o
- HMAC-SHA256(
$ e O; d: X- J4 _6 h, U& |8 p - "aa492a44bdf019c759defb1698c1d77690189973945491a756051cdc1207a449",3 k0 ]1 U+ L" H4 p, F6 ~
- joined_pairs,
* S3 c4 R+ {0 p2 k( l - ) = "371697738012ebd26a111ace4aff23ee265596cd64026c8c3677956a85ca1827"
复制代码 现在,将最后收到的结果与第 1 步中的 hash 值进行比较,我们可以看到它们是相等的。 这意味着,我们可以信任传递的初始数据。+ I, f# t1 w7 \. \' C d n
" @, M% g% i4 x" o \% B/ _可以查看参数列表 。1 }. B& y ]# Y$ B1 z- P
# B) L+ g! ?; ]' z, Y |