diff --git a/docs/misc/sign/wbi.md b/docs/misc/sign/wbi.md index 68ba566..0459048 100644 --- a/docs/misc/sign/wbi.md +++ b/docs/misc/sign/wbi.md @@ -279,147 +279,163 @@ bar=514&baz=1919810&foo=114&wts=1684805578&w_rid=bb97e15f28edf445a0e4420d36f0157 package main import ( - "crypto/md5" - "encoding/hex" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "sort" - "strconv" - "strings" - "sync" - "time" + "crypto/md5" + "encoding/hex" + "fmt" + "io" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "sync" + "time" - "github.com/tidwall/gjson" + "github.com/tidwall/gjson" ) -var mixinKeyEncTab = []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, +var ( + mixinKeyEncTab = []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, + } + cache sync.Map + lastUpdateTime time.Time +) + +func main() { + urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091" + newUrlStr, err := signAndGenerateURL(urlStr) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + req, err := http.NewRequest("GET", newUrlStr, nil) + if err != nil { + fmt.Printf("Error: %s", err) + return + } + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") + response, err := http.DefaultClient.Do(req) + if err != nil { + fmt.Printf("Request failed: %s", err) + return + } + defer response.Body.Close() + body, err := io.ReadAll(response.Body) + if err != nil { + fmt.Printf("Failed to read response: %s", err) + return + } + fmt.Println(string(body)) +} + +func signAndGenerateURL(urlStr string) (string, error) { + urlObj, err := url.Parse(urlStr) + if err != nil { + return "", err + } + imgKey, subKey := getWbiKeysCached() + query := urlObj.Query() + params := map[string]string{} + for k, v := range query { + params[k] = v[0] + } + newParams := encWbi(params, imgKey, subKey) + for k, v := range newParams { + query.Set(k, v) + } + urlObj.RawQuery = query.Encode() + newUrlStr := urlObj.String() + return newUrlStr, nil +} + +func encWbi(params map[string]string, imgKey, subKey string) map[string]string { + mixinKey := getMixinKey(imgKey + subKey) + currTime := strconv.FormatInt(time.Now().Unix(), 10) + params["wts"] = currTime + + // Sort keys + keys := make([]string, 0, len(params)) + for k := range params { + keys = append(keys, k) + } + sort.Strings(keys) + + // Remove unwanted characters + for k, v := range params { + v = sanitizeString(v) + params[k] = v + } + + // Build URL parameters + query := url.Values{} + for _, k := range keys { + query.Set(k, params[k]) + } + queryStr := query.Encode() + + // Calculate w_rid + hash := md5.Sum([]byte(queryStr + mixinKey)) + params["w_rid"] = hex.EncodeToString(hash[:]) + return params } func getMixinKey(orig string) string { - var str strings.Builder - for _, v := range mixinKeyEncTab { - if v < len(orig) { - str.WriteByte(orig[v]) - } - } - return str.String()[:32] -} -func EncWbi(params map[string]string, imgKey string, subKey string) map[string]string { - mixinKey := getMixinKey(imgKey + subKey) - currTime := strconv.FormatInt(time.Now().Unix(), 10) - params["wts"] = currTime - // Sort keys - keys := make([]string, 0, len(params)) - for k := range params { - keys = append(keys, k) - } - sort.Strings(keys) - // Remove unwanted characters - for k, v := range params { - v = strings.ReplaceAll(v, "!", "") - v = strings.ReplaceAll(v, "'", "") - v = strings.ReplaceAll(v, "(", "") - v = strings.ReplaceAll(v, ")", "") - v = strings.ReplaceAll(v, "*", "") - params[k] = v - } - // Build URL parameters - var str strings.Builder - for _, k := range keys { - str.WriteString(fmt.Sprintf("%s=%s&", k, params[k])) - } - query := strings.TrimSuffix(str.String(), "&") - // Calculate w_rid - hash := md5.Sum([]byte(query + mixinKey)) - params["w_rid"] = hex.EncodeToString(hash[:]) - return params + var str strings.Builder + for _, v := range mixinKeyEncTab { + if v < len(orig) { + str.WriteByte(orig[v]) + } + } + return str.String()[:32] } -var cache sync.Map -var lastUpdateTime time.Time +func sanitizeString(s string) string { + unwantedChars := []string{"!", "'", "(", ")", "*"} + for _, char := range unwantedChars { + s = strings.ReplaceAll(s, char, "") + } + return s +} func updateCache() { - if time.Now().Sub(lastUpdateTime).Minutes() < 10 { - return - } - imgKey, subKey := GetWbiKeys() - cache.Store("imgKey", imgKey) - cache.Store("subKey", subKey) - lastUpdateTime = time.Now() + if time.Since(lastUpdateTime).Minutes() < 10 { + return + } + imgKey, subKey := getWbiKeys() + cache.Store("imgKey", imgKey) + cache.Store("subKey", subKey) + lastUpdateTime = time.Now() } -func GetWbiKeysCached() (string, string) { - updateCache() - imgKeyI, _ := cache.Load("imgKey") - subKeyI, _ := cache.Load("subKey") - return imgKeyI.(string), subKeyI.(string) +func getWbiKeysCached() (string, string) { + updateCache() + imgKeyI, _ := cache.Load("imgKey") + subKeyI, _ := cache.Load("subKey") + return imgKeyI.(string), subKeyI.(string) } -func GetWbiKeys() (string, string) { - resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav") - if err != nil { - fmt.Println("Error:", err) - return "", "" - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - fmt.Println("Error:", err) - return "", "" - } - json := string(body) - imgURL := gjson.Get(json, "data.wbi_img.img_url").String() - subURL := gjson.Get(json, "data.wbi_img.sub_url").String() - imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0] - subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0] - return imgKey, subKey -} - -func SignURL(urlStr string) string { - urlObj, _ := url.Parse(urlStr) - imgKey, subKey := GetWbiKeysCached() - fmt.Println(imgKey, subKey) - query := urlObj.Query() - params := map[string]string{} - for k, v := range query { - params[k] = v[0] - } - newParams := EncWbi(params, imgKey, subKey) - for k, v := range newParams { - query.Set(k, v) - } - urlObj.RawQuery = query.Encode() - newUrlStr := urlObj.String() - return newUrlStr -} -func main() { - urlStr := "https://api.bilibili.com/x/space/wbi/acc/info?mid=1850091" - newUrlStr := utils.SignURL(urlStr) // 签名 - req, err := http.NewRequest("GET", newUrlStr, nil) - if err != nil { - return nil, err - } - // 设置请求头,模拟浏览器 - req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36") - response, err := http.DefaultClient.Do(req) - fmt.Println(newUrlStr) - if err != nil { - fmt.Printf("请求发送失败:%s", err) - return nil, err - } - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) - if err != nil { - fmt.Printf("读取响应失败:%s", err) - return nil, err - } - fmt.Println(string(body)) +func getWbiKeys() (string, string) { + resp, err := http.Get("https://api.bilibili.com/x/web-interface/nav") + if err != nil { + fmt.Printf("Error: %s", err) + return "", "" + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + fmt.Printf("Error: %s", err) + return "", "" + } + json := string(body) + imgURL := gjson.Get(json, "data.wbi_img.img_url").String() + subURL := gjson.Get(json, "data.wbi_img.sub_url").String() + imgKey := strings.Split(strings.Split(imgURL, "/")[len(strings.Split(imgURL, "/"))-1], ".")[0] + subKey := strings.Split(strings.Split(subURL, "/")[len(strings.Split(subURL, "/"))-1], ".")[0] + return imgKey, subKey } ```