B站用户登录状态刷新接口开发:基于哔哩哔哩-API收集整理的会话保持实现
背景与痛点
你是否遇到过B站第三方应用频繁要求重新登录的问题?自从2023年起,B站Web端Cookie会随着敏感接口访问逐渐失效,官方通过动态加载iframe方式实现Cookie刷新,并引入refresh_token字段进行持久化保存,这是一种官方的风控机制实现。本文将基于哔哩哔哩-API收集整理项目的Web端Cookie刷新文档,详细介绍如何实现B站用户登录状态的自动刷新。
刷新流程概述
B站登录状态刷新流程主要包括以下步骤:
- 检查Cookie是否需要刷新
- 生成CorrespondPath签名
- 获取refresh_csrf实时刷新口令
- 刷新Cookie获取新会话
- 确认更新使旧会话失效
- SSO站点跨域登录保持全局会话
检查是否需要刷新Cookie
首先需要调用Cookie信息接口判断当前会话是否需要刷新,请求地址为:
https://passport.bilibili.com/x/passport-login/web/cookie/info
请求方式为GET,需要携带当前Cookie信息,主要参数如下:
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|---|---|---|---|---|
| csrf | str | CSRF Token(位于 Cookie) | 非必要 | 位于Cookie中的bili_jct字段 |
响应示例:
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"refresh": false,
"timestamp": 1684466082562
}
}
当data.refresh为true时,表示需要刷新Cookie,同时返回的timestamp将用于后续的CorrespondPath生成。详细接口定义可参考Cookie刷新文档。
生成CorrespondPath算法
CorrespondPath是通过RSA-OAEP算法加密生成的签名,用于后续获取refresh_csrf。算法细节如下:
- 将
refresh_${timestamp}作为消息体(timestamp为当前毫秒时间戳) - 使用B站公钥进行RSA-OAEP算法加密
- 密文通过小写Base16编码为字符串
B站提供的公钥JWK格式:
{
"kty": "RSA",
"n": "y4HdjgJHBlbaBN04VERG4qNBIFHP6a3GozCl75AihQloSWCXC5HDNgyinEnhaQ_4-gaMud_GF50elYXLlCToR9se9Z8z433U3KjM-3Yx7ptKkmQNAMggQwAVKgq3zYAoidNEWuxpkY_mAitTSRLnsJW-NCTa0bqBFF6Wm1MxgfE",
"e": "AQAB"
}
PEM格式:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
JNrRuoEUXpabUzGB8QIDAQAB
-----END PUBLIC KEY-----
Python实现示例
需要安装pycryptodome依赖:
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
import binascii
import time
key = RSA.importKey('''\
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0Eg
Uc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71
nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40
JNrRuoEUXpabUzGB8QIDAQAB
-----END PUBLIC KEY-----''')
def getCorrespondPath(ts):
cipher = PKCS1_OAEP.new(key, SHA256)
encrypted = cipher.encrypt(f'refresh_{ts}'.encode())
return binascii.b2a_hex(encrypted).decode()
ts = round(time.time() * 1000)
print(getCorrespondPath(ts))
运行结果示例:
47bbd615f333d6a2c597bbb46ad47a6e59752a305a2f545d3ba5d49ca055309347796f80d257613696d36170c57443a0e9dea2b47f83b0b4224d431e46124fadd9a24c8fa468147e8bf2d2501eaacae43310e19bf58fc4a728d80c90b9401afcfc1536ba9a2f6438ea53c0b2652f8b8d01c87355dd5a5da51de998b1a35d519a
除Python外,项目还提供了JavaScript、Kotlin、Java和Go等多种语言的实现示例。
获取refresh_csrf实时刷新口令
使用生成的CorrespondPath访问以下URL获取refresh_csrf:
https://www.bilibili.com/correspond/1/{correspondPath}
请求方式为GET,需要携带当前Cookie,返回的HTML页面中包含refresh_csrf信息,位于id为"1-name"的div标签中:
<div id="1-name">b0cc8411ded2f9db2cff2edb3123acac</div>
这里的b0cc8411ded2f9db2cff2edb3123acac就是实时刷新口令refresh_csrf。
获取refresh_csrf流程
刷新Cookie获取新会话
使用获取到的refresh_csrf调用Cookie刷新接口,请求地址:
https://passport.bilibili.com/x/passport-login/web/cookie/refresh
请求方式为POST,鉴权方式为Cookie,主要参数如下:
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|---|---|---|---|---|
| csrf | str | CSRF Token | 必要 | 位于Cookie中的bili_jct字段 |
| refresh_csrf | str | 实时刷新口令 | 必要 | 通过获取refresh_csrf步骤获得 |
| source | str | 访问来源? | 必要 | 一般为main_web |
| refresh_token | str | 持久化刷新口令 | 必要 | localStorage中的ac_time_value字段,在登录成功后返回并保存 |
刷新成功后,服务器会返回新的refresh_token,并设置以下Cookie项:
- sid
- DedeUserID
- DedeUserID__ckMd5
- SESSDATA
- bili_jct
响应示例:
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"status": 0,
"message": "",
"refresh_token": "ae1bd1149b56af9743ffe7bbbeff3e51"
}
}
确认更新使旧会话失效
为确保账号安全,需要调用确认更新接口使旧的refresh_token对应的Cookie失效,请求地址:
https://passport.bilibili.com/x/passport-login/web/confirm/refresh
请求方式为POST,主要参数如下:
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|---|---|---|---|---|
| csrf | str | CSRF Token(位于cookie) | 必要 | 从新的cookie中获取,位于Cookie中的bili_jct字段 |
| refresh_token | str | 旧的持久化刷新口令 | 必要 | 在刷新前localStorage中的ac_time_value获取,并非刷新后返回的值 |
响应示例:
{
"code": 0,
"message": "0",
"ttl": 1
}
SSO站点跨域登录
最后需要进行SSO(单点登录)站点跨域登录,确保所有B站相关服务都能识别新的登录状态。
完整实现伪代码
cookie, refresh_token = 进行登录操作() # 可以是二维码/密码/短信验证码登录
while True:
if 每日第一次访问接口:
if 检查是否需要刷新(cookie):
CorrespondPath = 生成CorrespondPath(当前毫秒时间戳)
refresh_csrf = 获取refresh_csrf(CorrespondPath, cookie)
refresh_token_old = refresh_token # 必须保存旧的refresh_token备用
cookie, refresh_token = 刷新Cookie(refresh_token, refresh_csrf, cookie)
确认更新(refresh_token_old, cookie) # 需要新的Cookie以及旧的refresh_token
SSO站点跨域登录(cookie)
do_somethings(cookie) # 其他业务逻辑处理
注意事项
- cookie不会主动刷新,只有调用刷新接口才会刷新
- 只要不打开浏览器或删除localStorage的ac_time_value字段,cookie在真正失效前不会变化
- 刷新Cookie后必须调用确认更新接口,否则旧的refresh_token可能仍有效,存在安全风险
- 所有加密操作需要严格按照B站提供的算法实现,特别是RSA-OAEP参数要匹配
- 持久化存储refresh_token时需要注意安全,避免泄露
总结
通过以上步骤,我们可以实现B站用户登录状态的自动刷新,保持长期有效的会话连接。完整的接口文档和更多实现细节可以参考项目中的Web端Cookie刷新文档。
如果您在实现过程中遇到问题,可以查阅项目的贡献指南或提交issue寻求帮助。
注:本文内容基于哔哩哔哩-API收集整理项目的公开文档,具体实现时请遵守B站相关规定,合理使用API接口。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



