返回提交历史
Modified
docs/misc/sign/wbi.md
+86
-46
XFEstudio/bilibili-API-collect
给Wbi签名算法的Demo添加C#实现 (#719)
Co-authored-by: 社会易姐QwQ <45892418+SocialSisterYi@users.noreply.github.com>
63deb66
代码差异
1 个文件
+86
-46
@@ -115,7 +115,7 @@
115
115
116
116
## Wbi签名算法实现Demo
117
117
118
该 Demo 提供 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang) 语言
118
该 Demo 提供 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp) 语言
119
119
120
120
### Python
121
121
@@ -422,60 +422,100 @@ func main() {
422
422
fmt.Println(string(body))
423
423
}
424
424
```
425
### Java
426
425
427
需要 `hutool` 依赖
426
### CSharp
428
427
429
```java
430
package com.example.demo;
428
无需依赖外部库
431
429
432
import cn.hutool.crypto.SecureUtil;
430
```cs
431
using System.Security.Cryptography;
432
using System.Text;
433
using System.Text.Json.Nodes;
433
434
434
import java.util.*;
435
class Program
436
{
437
private static HttpClient _httpClient = new();
435
438
436
public class WbiTest {
437
private static final int[] mixinKeyEncTab = new int[]{
438
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
439
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
440
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
441
36, 20, 34, 44, 52
439
private static readonly int[] MixinKeyEncTab =
440
{
441
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39,
442
12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63,
443
57, 62, 11, 36, 20, 34, 44, 52
442
444
};
443
445
444
public static String getMixinKey(String imgKey, String subKey) {
445
String s = imgKey + subKey;
446
StringBuilder key = new StringBuilder();
447
for (int i = 0; i < 32; i++) {
448
key.append(s.charAt(mixinKeyEncTab[i]));
449
}
450
return key.toString();
446
//对 imgKey 和 subKey 进行字符顺序打乱编码
447
private static string GetMixinKey(string orig)
448
{
449
return MixinKeyEncTab.Aggregate("", (s, i) => s + orig[i])[..32];
450
}
451
452
private static Dictionary<string, string> EncWbi(Dictionary<string, string> parameters, string imgKey,
453
string subKey)
454
{
455
string mixinKey = GetMixinKey(imgKey + subKey);
456
string currTime = DateTimeOffset.Now.ToUnixTimeSeconds().ToString();
457
//添加 wts 字段
458
parameters["wts"] = currTime;
459
// 按照 key 重排参数
460
parameters = parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
461
//过滤 value 中的 "!'()*" 字符
462
parameters = parameters.ToDictionary(
463
kvp => kvp.Key,
464
kvp => new string(kvp.Value.Where(chr => !"!'()*".Contains(chr)).ToArray())
465
);
466
// 序列化参数
467
string query = new FormUrlEncodedContent(parameters).ReadAsStringAsync().Result;
468
//计算 w_rid
469
using MD5 md5 = MD5.Create();
470
byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query + mixinKey));
471
string wbiSign = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
472
parameters["w_rid"] = wbiSign;
473
474
return parameters;
475
}
476
477
// 获取最新的 img_key 和 sub_key
478
private static async Task<(string, string)> GetWbiKeys()
479
{
480
HttpResponseMessage responseMessage = await _httpClient.SendAsync(new HttpRequestMessage
481
{
482
Method = HttpMethod.Get,
483
RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"),
484
});
485
486
JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!;
487
488
string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!;
489
imgUrl = imgUrl.Split("/")[^1].Split(".")[0];
490
491
string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!;
492
subUrl = subUrl.Split("/")[^1].Split(".")[0];
493
return (imgUrl, subUrl);
451
494
}
452
495
453
public static void main(String[] args) {
454
String imgKey = "653657f524a547ac981ded72ea172057";
455
String subKey = "6e4909c702f846728e64f6007736a338";
456
String mixinKey = getMixinKey(imgKey, subKey);
457
System.out.println(mixinKey);
458
//72136226c6a73669787ee4fd02a74c27
459
//{
460
// foo: '114',
461
// bar: '514',
462
// zab: 1919810
463
//}
464
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
465
map.put("foo", "114");
466
map.put("bar", "514");
467
map.put("zab", 1919810);
468
map.put("wts", System.currentTimeMillis() / 1000);
469
StringJoiner param = new StringJoiner("&");
470
//排序 + 拼接字符串
471
map.entrySet().stream()
472
.sorted(Map.Entry.comparingByKey())
473
.forEach(entry -> param.add(entry.getKey() + "=" + entry.getValue().toString()));
474
String s = param + mixinKey;
475
String wbiSign = SecureUtil.md5(s);
476
System.out.println(wbiSign);
477
String finalParam = param + "&w_rid=" + wbiSign;
478
System.out.println(finalParam);
496
public static async Task Main()
497
{
498
var (imgKey, subKey) = await GetWbiKeys();
499
500
Dictionary<string, string> signedParams = EncWbi(
501
parameters: new Dictionary<string, string>
502
{
503
{ "foo", "114" },
504
{ "bar", "514" },
505
{ "baz", "1919810" }
506
},
507
imgKey: imgKey,
508
subKey: subKey
509
);
510
511
string query = await new FormUrlEncodedContent(signedParams).ReadAsStringAsync();
512
513
Console.WriteLine(query);
479
514
}
480
515
}
516
```
517
输出内容为进行 Wbi 签名的后参数的 url query 形式
518
519
```
520
bar=514&baz=1919810&foo=114&wts=1687541921&w_rid=26e82b1b9b3a11dbb1807a9228a40d3b
481
521
```