哔哩哔哩-API收集整理:API签名验证失败常见原因与解决方法

哔哩哔哩-API收集整理:API签名验证失败常见原因与解决方法

什么是WBI签名验证

自2023年3月起,哔哩哔哩Web端部分接口开始采用WBI签名鉴权,表现在REST API请求时在Query param中添加了w_ridwts字段。WBI签名鉴权独立于APP鉴权与其他Cookie鉴权,目前被认为是一种Web端风控手段。

当请求WBI签名鉴权接口时,若签名参数w_rid与时间戳wts缺失、错误,会返回v_voucher,如:

{"code":0,"message":"0","ttl":1,"data":{"v_voucher":"voucher_******"}}

哔哩哔哩LOGO

常见签名验证失败原因分析

1. 签名参数缺失或错误

最常见的问题是未正确添加w_ridwts参数。根据WBI签名文档,这两个参数是必需的,缺少任何一个都会导致验证失败。

2. 时间戳过期

wts字段的值应为当前以秒为单位的Unix时间戳。如果时间戳与服务器时间相差过大(通常超过5分钟),签名将被视为无效。这也是为什么在进行API调用时,动态生成时间戳非常重要。

3. img_key和sub_key不正确或过期

img_keysub_key是生成签名的关键参数,它们通常每日更替。如果使用了过期的密钥或错误地从图片URL中提取密钥,会导致签名验证失败。

哔哩哔哩验证流程图

4. 参数排序和编码错误

在生成签名前,需要对参数按key进行升序排序,并正确编码特殊字符。特别是中文和空格等字符,必须使用UTF-8编码,且空格应编码为%20而非+

5. mixin_key生成错误

mixin_key的生成需要特定的字符重排算法,如果重排映射表或截取长度不正确,会导致最终签名错误。

解决方法与最佳实践

1. 正确获取和缓存密钥

应从nav接口bili_ticket接口获取最新的img_keysub_key,并实现合理的缓存机制。

def getWbiKeys() -> tuple[str, str]:
    '获取最新的 img_key 和 sub_key'
    headers = {
        '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',
        'Referer': 'https://www.bilibili.com/'
    }
    resp = requests.get('https://api.bilibili.com/x/web-interface/nav', headers=headers)
    resp.raise_for_status()
    json_content = resp.json()
    img_url: str = json_content['data']['wbi_img']['img_url']
    sub_url: str = json_content['data']['wbi_img']['sub_url']
    img_key = img_url.rsplit('/', 1)[1].split('.')[0]
    sub_key = sub_url.rsplit('/', 1)[1].split('.')[0]
    return img_key, sub_key

2. 正确实现签名生成算法

确保严格按照文档实现参数排序、编码和mixin_key生成。以下是Python实现示例:

def encWbi(params: dict, img_key: str, sub_key: str):
    '为请求参数进行 wbi 签名'
    mixin_key = getMixinKey(img_key + sub_key)
    curr_time = round(time.time())
    params['wts'] = curr_time                                   # 添加 wts 字段
    params = dict(sorted(params.items()))                       # 按照 key 重排参数
    # 过滤 value 中的 "!'()*" 字符
    params = {
        k : ''.join(filter(lambda chr: chr not in "!'()*", str(v)))
        for k, v 
        in params.items()
    }
    query = urllib.parse.urlencode(params)                      # 序列化参数
    wbi_sign = md5((query + mixin_key).encode()).hexdigest()    # 计算 w_rid
    params['w_rid'] = wbi_sign
    return params

3. 处理特殊字符编码

确保对参数值进行正确的URL编码,特别是中文和特殊符号:

const value = params[key].toString().replace(chr_filter, '')
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`

哔哩哔哩API示例

4. 定期更新签名实现

B站API可能会不定期更新签名算法,建议关注官方文档的更新,并定期检查你的实现是否仍然有效。

5. 使用现成的签名库

如果可能,尽量使用经过验证的第三方库或官方SDK,以减少手动实现带来的错误。项目中提供了多种语言的签名实现示例,包括Python、JavaScript、Golang等。

常见问题排查步骤

  1. 检查是否正确添加了w_ridwts参数
  2. 验证时间戳是否与当前时间同步
  3. 确认使用了最新的img_keysub_key
  4. 检查参数排序和编码是否符合要求
  5. 验证mixin_key生成过程是否正确
  6. 对比官方示例,检查签名生成结果是否一致

哔哩哔哩错误提示

总结

WBI签名验证虽然增加了API调用的复杂度,但通过正确理解签名机制、严格按照规范实现,并遵循最佳实践,可以有效避免验证失败的问题。如果遇到复杂问题,建议参考项目中的详细文档或寻求社区支持。

记住,API签名机制的目的是为了保护API的安全使用,正确实现签名不仅能避免调用失败,也是良好开发实践的重要组成部分。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值