返回提交历史
Modified
docs/misc/sign/wbi.md
+99
-3
XFEstudio/bilibili-API-collect
feat. wbi签名算法添加typescript实现 (#1031)
* feat. wbi签名算法添加typescript实现 * fix. Fixed missing quotes in User-Agent header in WBI JS demo
20940ee
代码差异
1 个文件
+99
-3
@@ -201,7 +201,10 @@ bar=514&baz=1919810&foo=114&wts=1702204169&w_rid=d3cbd2a2316089117134038bf4caf44
201
201
202
202
### JavaScript
203
203
204
需要 `axios`、`md5` 依赖
204
需要 `fetch`(浏览器、NodeJS等环境自带)、`md5` 依赖
205
206
<CodeGroup>
207
<CodeGroupItem title="JavaScript">
205
208
206
209
```javascript
207
210
import md5 from 'md5'
@@ -244,8 +247,8 @@ async function getWbiKeys() {
244
247
const res = await fetch('https://api.bilibili.com/x/web-interface/nav', {
245
248
headers: {
246
249
// SESSDATA 字段
247
Cookie: "SESSDATA=xxxxxx",
248
User-Agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
250
Cookie: 'SESSDATA=xxxxxx',
251
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
249
252
Referer: 'https://www.bilibili.com/'//对于直接浏览器调用可能不适用
250
253
}
251
254
})
@@ -275,6 +278,99 @@ async function main() {
275
278
main()
276
279
```
277
280
281
</CodeGroupItem>
282
283
<CodeGroupItem title="TypeScript">
284
285
```typescript
286
import md5 from 'md5'
287
288
const mixinKeyEncTab = [
289
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
290
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
291
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
292
36, 20, 34, 44, 52
293
]
294
295
// 对 imgKey 和 subKey 进行字符顺序打乱编码
296
const getMixinKey = (orig: string) =>
297
mixinKeyEncTab
298
.map((n) => orig[n])
299
.join("")
300
.slice(0, 32);
301
302
// 为请求参数进行 wbi 签名
303
function encWbi(
304
params: { [key: string]: string | number | object },
305
img_key: string,
306
sub_key: string
307
) {
308
const mixin_key = getMixinKey(img_key + sub_key),
309
curr_time = Math.round(Date.now() / 1000),
310
chr_filter = /[!'()*]/g;
311
312
Object.assign(params, { wts: curr_time }); // 添加 wts 字段
313
// 按照 key 重排参数
314
const query = Object.keys(params)
315
.sort()
316
.map((key) => {
317
// 过滤 value 中的 "!'()*" 字符
318
const value = params[key].toString().replace(chr_filter, "");
319
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
320
})
321
.join("&");
322
323
const wbi_sign = md5(query + mixin_key); // 计算 w_rid
324
325
return query + "&w_rid=" + wbi_sign;
326
}
327
// 获取最新的 img_key 和 sub_key
328
async function getWbiKeys(SESSDATA: string) {
329
const res = await fetch('https://api.bilibili.com/x/web-interface/nav', {
330
headers: {
331
// SESSDATA 字段
332
Cookie: `SESSDATA=${SESSDATA}`,
333
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
334
Referer: 'https://www.bilibili.com/'//对于直接浏览器调用可能不适用
335
}
336
})
337
const {
338
data: {
339
wbi_img: { img_url, sub_url },
340
},
341
} = (await res.json()) as {
342
data: {
343
wbi_img: { img_url: string; sub_url: string };
344
};
345
};
346
347
return {
348
img_key: img_url.slice(
349
img_url.lastIndexOf('/') + 1,
350
img_url.lastIndexOf('.')
351
),
352
sub_key: sub_url.slice(
353
sub_url.lastIndexOf('/') + 1,
354
sub_url.lastIndexOf('.')
355
)
356
}
357
}
358
359
async function main() {
360
const web_keys = await getWbiKeys("SESSDATA的值")
361
const params = { foo: '114', bar: '514', baz: 1919810 },
362
img_key = web_keys.img_key,
363
sub_key = web_keys.sub_key
364
const query = encWbi(params, img_key, sub_key)
365
console.log(query)
366
}
367
368
main()
369
```
370
371
</CodeGroupItem>
372
</CodeGroup>
373
278
374
输出内容为进行 Wbi 签名的后参数的 url query 形式
279
375
280
376
```