From 63deb66605188519d6a22b8e9bc396aca72182ad Mon Sep 17 00:00:00 2001 From: kurisu_u <73207840+lanyeeee@users.noreply.github.com> Date: Wed, 28 Jun 2023 18:18:33 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=99Wbi=E7=AD=BE=E5=90=8D=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E7=9A=84Demo=E6=B7=BB=E5=8A=A0C#=E5=AE=9E=E7=8E=B0=20?= =?UTF-8?q?(#719)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 社会易姐QwQ <45892418+SocialSisterYi@users.noreply.github.com> --- docs/misc/sign/wbi.md | 132 +++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 46 deletions(-) diff --git a/docs/misc/sign/wbi.md b/docs/misc/sign/wbi.md index 9aa4088..5f46543 100644 --- a/docs/misc/sign/wbi.md +++ b/docs/misc/sign/wbi.md @@ -115,7 +115,7 @@ ## Wbi签名算法实现Demo -该 Demo 提供 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang) 语言 +该 Demo 提供 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp) 语言 ### Python @@ -422,60 +422,100 @@ func main() { fmt.Println(string(body)) } ``` -### Java -需要 `hutool` 依赖 +### CSharp -```java -package com.example.demo; +无需依赖外部库 -import cn.hutool.crypto.SecureUtil; +```cs +using System.Security.Cryptography; +using System.Text; +using System.Text.Json.Nodes; -import java.util.*; +class Program +{ + private static HttpClient _httpClient = new(); -public class WbiTest { - private static final int[] mixinKeyEncTab = new int[]{ - 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, 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, 57, 62, 11, - 36, 20, 34, 44, 52 + private static readonly int[] MixinKeyEncTab = + { + 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, + 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, + 57, 62, 11, 36, 20, 34, 44, 52 }; - public static String getMixinKey(String imgKey, String subKey) { - String s = imgKey + subKey; - StringBuilder key = new StringBuilder(); - for (int i = 0; i < 32; i++) { - key.append(s.charAt(mixinKeyEncTab[i])); - } - return key.toString(); + //对 imgKey 和 subKey 进行字符顺序打乱编码 + private static string GetMixinKey(string orig) + { + return MixinKeyEncTab.Aggregate("", (s, i) => s + orig[i])[..32]; } - public static void main(String[] args) { - String imgKey = "653657f524a547ac981ded72ea172057"; - String subKey = "6e4909c702f846728e64f6007736a338"; - String mixinKey = getMixinKey(imgKey, subKey); - System.out.println(mixinKey); - //72136226c6a73669787ee4fd02a74c27 - //{ - // foo: '114', - // bar: '514', - // zab: 1919810 - //} - LinkedHashMap map = new LinkedHashMap<>(); - map.put("foo", "114"); - map.put("bar", "514"); - map.put("zab", 1919810); - map.put("wts", System.currentTimeMillis() / 1000); - StringJoiner param = new StringJoiner("&"); - //排序 + 拼接字符串 - map.entrySet().stream() - .sorted(Map.Entry.comparingByKey()) - .forEach(entry -> param.add(entry.getKey() + "=" + entry.getValue().toString())); - String s = param + mixinKey; - String wbiSign = SecureUtil.md5(s); - System.out.println(wbiSign); - String finalParam = param + "&w_rid=" + wbiSign; - System.out.println(finalParam); + private static Dictionary EncWbi(Dictionary parameters, string imgKey, + string subKey) + { + string mixinKey = GetMixinKey(imgKey + subKey); + string currTime = DateTimeOffset.Now.ToUnixTimeSeconds().ToString(); + //添加 wts 字段 + parameters["wts"] = currTime; + // 按照 key 重排参数 + parameters = parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value); + //过滤 value 中的 "!'()*" 字符 + parameters = parameters.ToDictionary( + kvp => kvp.Key, + kvp => new string(kvp.Value.Where(chr => !"!'()*".Contains(chr)).ToArray()) + ); + // 序列化参数 + string query = new FormUrlEncodedContent(parameters).ReadAsStringAsync().Result; + //计算 w_rid + using MD5 md5 = MD5.Create(); + byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query + mixinKey)); + string wbiSign = BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); + parameters["w_rid"] = wbiSign; + + return parameters; + } + + // 获取最新的 img_key 和 sub_key + private static async Task<(string, string)> GetWbiKeys() + { + HttpResponseMessage responseMessage = await _httpClient.SendAsync(new HttpRequestMessage + { + Method = HttpMethod.Get, + RequestUri = new Uri("https://api.bilibili.com/x/web-interface/nav"), + }); + + JsonNode response = JsonNode.Parse(await responseMessage.Content.ReadAsStringAsync())!; + + string imgUrl = (string)response["data"]!["wbi_img"]!["img_url"]!; + imgUrl = imgUrl.Split("/")[^1].Split(".")[0]; + + string subUrl = (string)response["data"]!["wbi_img"]!["sub_url"]!; + subUrl = subUrl.Split("/")[^1].Split(".")[0]; + return (imgUrl, subUrl); + } + + public static async Task Main() + { + var (imgKey, subKey) = await GetWbiKeys(); + + Dictionary signedParams = EncWbi( + parameters: new Dictionary + { + { "foo", "114" }, + { "bar", "514" }, + { "baz", "1919810" } + }, + imgKey: imgKey, + subKey: subKey + ); + + string query = await new FormUrlEncodedContent(signedParams).ReadAsStringAsync(); + + Console.WriteLine(query); } } +``` +输出内容为进行 Wbi 签名的后参数的 url query 形式 + +``` +bar=514&baz=1919810&foo=114&wts=1687541921&w_rid=26e82b1b9b3a11dbb1807a9228a40d3b ``` \ No newline at end of file