From 8f419c1c9cdb9b32d6441c735647332ccdb21dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=80=E1=B4=8D=E1=B4=9B=E1=B4=8F=E1=B4=80=E1=B4=87?= =?UTF-8?q?=CA=80?= Date: Sat, 20 Jul 2024 17:53:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8E=B7=E5=8F=96=20w?= =?UTF-8?q?bi=20=E7=AD=BE=E5=90=8D=E7=9A=84=20rust=20=E5=AE=9E=E7=8E=B0=20?= =?UTF-8?q?(#1059)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复获取 wbi 签名的 rust 实现 * chore: 在最上面的介绍里补上 Rust 的超链接 --- docs/misc/sign/wbi.md | 97 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/docs/misc/sign/wbi.md b/docs/misc/sign/wbi.md index 7c0d9c3..be86781 100644 --- a/docs/misc/sign/wbi.md +++ b/docs/misc/sign/wbi.md @@ -120,7 +120,7 @@ ## Demo -含 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp)、[Java](#Java)、[Swift](#Swift)、[C++](#CPlusPlus) 语言编写的 Demo 。 +含 [Python](#Python)、[JavaScript](#JavaScript)、[Golang](#Golang)、[C#](#CSharp)、[Java](#Java)、[Swift](#Swift)、[C++](#CPlusPlus)、[Rust](#Rust) 语言编写的 Demo 。 ### Python @@ -867,6 +867,7 @@ struct ResWbi { fn get_mixin_key(orig: &[u8]) -> String { MIXIN_KEY_ENC_TAB .iter() + .take(32) .map(|&i| orig[i] as char) .collect::() } @@ -891,23 +892,34 @@ fn get_url_encoded(s: &str) -> String { } // 为请求参数进行 wbi 签名 -fn encode_wbi(params: &mut Vec<(&str, String)>, (img_key, sub_key): (String, String)) -> String { - let mixin_key = get_mixin_key((img_key + &sub_key).as_bytes()); +fn encode_wbi(params: Vec<(&str, String)>, (img_key, sub_key): (String, String)) -> String { let cur_time = match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(t) => t.as_secs(), Err(_) => panic!("SystemTime before UNIX EPOCH!"), }; + _encode_wbi(params, (img_key, sub_key), cur_time) +} + +fn _encode_wbi( + mut params: Vec<(&str, String)>, + (img_key, sub_key): (String, String), + timestamp: u64, +) -> String { + let mixin_key = get_mixin_key((img_key + &sub_key).as_bytes()); // 添加当前时间戳 - params.push(("wts", cur_time.to_string())); + params.push(("wts", timestamp.to_string())); // 重新排序 params.sort_by(|a, b| a.0.cmp(b.0)); - let query = params.iter().fold(String::from(""), |acc, (k, v)| { - acc + format!("{}={}&", get_url_encoded(k), get_url_encoded(v)).as_str() - }); - + // 拼接参数 + let query = params + .iter() + .map(|(k, v)| format!("{}={}", get_url_encoded(k), get_url_encoded(v))) + .collect::>() + .join("&"); + // 计算签名 let web_sign = format!("{:?}", md5::compute(query.clone() + &mixin_key)); - - query + &format!("w_rid={}", web_sign) + // 返回最终的 query + query + &format!("&w_rid={}", web_sign) } async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> { @@ -922,23 +934,76 @@ async fn get_wbi_keys() -> Result<(String, String), reqwest::Error> { .await? .json::() .await?; + Ok(( + take_filename(wbi_img.img_url).unwrap(), + take_filename(wbi_img.sub_url).unwrap(), + )) +} - Ok((wbi_img.img_url, wbi_img.sub_url)) +fn take_filename(url: String) -> Option { + url.rsplit_once('/') + .and_then(|(_, s)| s.rsplit_once('.')) + .map(|(s, _)| s.to_string()) } #[tokio::main] async fn main() { - let urls = get_wbi_keys().await.unwrap(); - let mut params = vec![ + let keys = get_wbi_keys().await.unwrap(); + let params = vec![ ("foo", String::from("114")), ("bar", String::from("514")), ("baz", String::from("1919810")), ]; - - let query = encode_wbi(&mut params, urls); - + let query = encode_wbi(params, keys); println!("{}", query); } + +// 取自文档描述的测试用例 +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get_filename() { + assert_eq!( + take_filename( + "https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png".to_string() + ), + Some("7cd084941338484aae1ad9425b84077c".to_string()) + ); + } + + #[test] + fn test_get_mixin_key() { + let concat_key = + "7cd084941338484aae1ad9425b84077c".to_string() + "4932caff0ff746eab6f01bf08b70ac45"; + assert_eq!( + get_mixin_key(concat_key.as_bytes()), + "ea1db124af3c7062474693fa704f4ff8" + ); + } + + #[test] + fn test_encode_wbi() { + let params = vec![ + ("foo", String::from("114")), + ("bar", String::from("514")), + ("zab", String::from("1919810")), + ]; + assert_eq!( + _encode_wbi( + params, + ( + "7cd084941338484aae1ad9425b84077c".to_string(), + "4932caff0ff746eab6f01bf08b70ac45".to_string() + ), + 1702204169 + ), + "bar=514&foo=114&wts=1702204169&zab=1919810&w_rid=8f6f2b5b3d485fe1886cec6a0be8c5d4" + .to_string() + ) + } +} ``` ### Swift