From 598854c8034821d65c123763a0a3db0fb3d0bb51 Mon Sep 17 00:00:00 2001 From: Kamisato-Ayaka-233 <2627706725@qq.com> Date: Sat, 11 Feb 2023 17:14:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=89=B4=E6=9D=83=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 - other/authentication.md | 172 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 164 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b4f6b59..c3d781c 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,6 @@ - [ ] [验证码登录](genshin_impact/login/sms.md) - [ ] [用户信息](genshin_impact/user) - [ ] [基本信息](genshin_impact/user/info.md) - - [ ] [其它](genshin_impact/other/) - [ ] [公告](genshin_impact/other/announcement.md) diff --git a/other/authentication.md b/other/authentication.md index b953ff2..00bffc8 100644 --- a/other/authentication.md +++ b/other/authentication.md @@ -1,7 +1,6 @@ # 鉴权 - [请求头](#请求头) - - [米游社](#米游社) - [Cookie](#cookie) --- @@ -20,7 +19,6 @@ 可选请求头:`x-rpc-device_fp`、`x-rpc-device_name`、`x-rpc-device_model`、`x-rpc-sys_version`、`x-rpc-channel`。 -#### `x-rpc-app_version` #### `x-rpc-app_version` @@ -41,11 +39,29 @@ APP为`2`或`5`,网页为`4`。 与DS字段相关,DS生成需要`salt`,而不同的`x-rpc-client_type`对应该版本米游社的`salt`也不同。 -- `x-rpc-sys_version`(可选):安卓系统大版本版本号,例如Android 13则为`13`。 -- `x-rpc-channel`(可选):手机厂商,例如小米则为`xiaomi`。 -- `x-rpc-device_name`(可选):手机厂商和手机型号,例如小米11青春版则为`Xiaomi M2101K9C`。 -- `x-rpc-device_model`(可选):手机型号。 +#### `x-rpc-sys_version`(可选) +安卓系统大版本版本号,例如Android 13则为`13`。 + +#### `x-rpc-channel`(可选) + +手机厂商,例如小米则为`xiaomi`。 + +#### `x-rpc-device_name`(可选) + +手机厂商和手机型号,例如小米11青春版则为`Xiaomi M2101K9C`。 + +#### `x-rpc-device_model`(可选) + +手机型号。 + +#### `x-rpc-device_fp`(可选) + +向`https://public-data-api.mihoyo.com/device-fp/api/getFp`发送一些设备信息以获得。 + +#### `x-rpc-device_id` + +未知其规律,可以从请求中复制。 #### `x-rpc-page` @@ -53,6 +69,8 @@ APP为`2`或`5`,网页为`4`。 `3.1.3_#/ys` +`/ys` + #### `X-Requested-With` 国内版APP为`com.mihoyo.hyperion`。 @@ -63,10 +81,14 @@ APP为`2`或`5`,网页为`4`。 请求网站的协议与主机名。 +例如请求`https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/index`(通过原神UID获取角色信息)则该字段为`https://api-takumi-record.mihoyo.com`。 + #### `Host` 请求的网站的主机名。 +例如请求`https://api-takumi.mihoyo.com/account/auth/api/webLoginByPassword`(网页登录米游社)则该字段为`api-takumi.mihoyo.com`。 + #### `Referer` 在哪个网页发起的请求。 @@ -85,15 +107,149 @@ APP为`2`或`5`,网页为`4`。 无需验证请求头或`x-rpc-client_type`为`2`的API不需要设置请求头。 -但还是最好避免带有`python`等字样。 +但尽量避免带有`python`等字样。 -用户代理,为`Mozilla/5.0 (Linux; Android 13; M2101K9C Build/TKQ1.220829.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 miHoYoBBS/米游社版本号`。 +需要验证请求头的API的用户代理为`Mozilla/5.0 (Linux; Android 安卓大版本号; 手机型号 Build/TKQ1.220829.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 miHoYoBBS/米游社版本号`。 + +例如`Mozilla/5.0 (Linux; Android 13; M2101K9C Build/TKQ1.220829.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 miHoYoBBS/2.44.1` #### `DS` +_DS(Dynamic Secret,动态密钥)_ + +大多数API需要验证请求头中的`DS`字段。 + DS值通过一系列算法得出。 +##### 生成`DS` +`DS`的生成方式由以下因素影响: + +* 网页、中国版APP和国际版APP的生成算法不同。 +* 请求头的`x-rpc-client_type`字段,每个值都有其对应的生成算法。 +* 少数API有其单独的生成算法。 + +生成`DS`需要`salt`(为32个包含大写字母、小写字母、数字的字符串)。 + +`salt`在以下情况下不同: + +* 网页、中国版APP和国际版APP使用的`salt`不同。 +* 每个APP版本都存有其独有的`salt`。 +* 请求头的`x-rpc-client_type`字段,每个值使用的`salt`不同。 +* 少数API有其单独的`salt`(例如米游社社区签到)。 + +请在[这里](https://github.com/Kamisato-Ayaka-233/mihoyo-api-collect/issues/1#issue-1571906738)获取`salt`。 + + +###### 中国版APP: + +**当`x-rpc-client_type`为`5`时**: + +整体思路: + +1. 获取当前的Unix时间戳(整数)。 +1. 在100001到200000中选取随机整数。 +1. 若将发送Post请求,则将发送的数据转为JSON字符串,存储至变量(下文称`body`)。若将发送Get请求,则将URL参数进行英文字母顺序排序(键)后存储至变量(下文称`query`),例如URL参数为`server=cn_gf01&role_id=114514191`则结果为`role_id=222681079&server=cn_gf01`。若不需要传递数据或URL参数,则为空字符串。 +1. 格式化字符串:`salt={salt值}&t={第1步的结果}&r={第2步的结果}&b={第3步的body}&q={第3步的query}`。 +1. 将第4步的结果进行UTF-8编码,再进行MD5编码。 +1. 格式化字符串:`{第1步的结果},{第2步的结果},{第5步的结果}`。 + +Python: +```python +import time +import random +from hashlib import md5 + +# 将要使用的salt,此为2.44.1版本的salt。 +salt = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs" +# body和query一般来说不会同时存在。 +# 可以使用json库的dumps函数将对象转为JSON字符串。 +body = '{"role": "123456789"}' +# 可以使用urllib中的parse库的urlparse函数,传入URL,得到返回值中的query字段。 +# 将其转为列表(通过str.split("&")),通过sorted函数来排序,再用"&".join来将其转为最终值 +query = "&".join(sorted("server=cn_gf01&role_id=123456789".split("&"))) + +t = int(time.time()) +r = random.randint(100001, 200000) +main = f"salt={salt}&t={t}&r={r}&b={body}&q={query}" +ds = md5(main.encode(encoding='UTF-8')).hexdigest() + +final = f"{t},{r},{ds}" # 最终结果。 +``` + +**当`x-rpc-client_type`为`2`时**: + +整体思路: + +1. 获取当前的Unix时间戳(整数)。 +1. 在大写字母、小写字母、数字中随机抽出6个。 +1. 格式化字符串:`salt={salt值}&t={第1步的结果}&r={第2步的结果}`。 +1. 将第3步的结果进行UTF-8编码,再进行MD5编码。 +1. 格式化字符串:`{第1步的结果},{第2步的结果},{第4步的结果}`。 + +Python: +```python +import time +import random +from hashlib import md5 + + +lettersAndNumbers = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + +# 将要使用的salt,此为2.35.2版本的salt。 +salt = "ZSHlXeQUBis52qD1kEgKt5lUYed4b7Bb" + +t = int(time.time()) +r = "" +for _ in range(6): + r += random.choice(lettersAndNumbers) +main = f"salt={salt}&t={t}&r={r}" +ds = md5(main.encode(encoding='UTF-8')).hexdigest() + +final = f"{t},{r},{ds}" # 最终结果。 +``` + +**当`x-rpc-client_type`为`4`(网页)时**: + +未知 ## Cookie +一些API(例如文章点赞、签到等)需要登录账号,为Cookie的形式。 + +若API无需登录账号,就不需要设置Cookie。 + +### 米游社 + +网页(`x-rpc-client_type`为`4`)、APP端(`x-rpc-client_type`为`2`)的Cookie形式不同。 + +`x-rpc-client_type`为`5`则与网页的Cookie相同。 + +**网页:** + +以下字段必须有,否则服务器返回`10001`: + +* `ltoken_v2` +* `ltmid_v2` + +以下字段可选: + +* `cookie_token_v2` +* `account_mid_v2` - 与`ltmid_v2`相同 +* `account_id_v2` - 米游社UID +* `cookie_token_v2` +* `_MHYUUID` +* `DEVICEFP` +* `acw_tc` +* `ltuid_v2` - 米游社UID + +**APP:** + +以下字段必须有: + +* `stoken` +* `mid` + +以下字段可选: + +* `stuid` - 米游社UID