import{_ as d,c as r,a as o,b as t,d as e,e as l,w as a,r as i,o as p}from"./app-Dgsdh8A6.js";const c={};function u(D,s){const n=i("RouteLink");return p(),r("div",null,[s[35]||(s[35]=o('
当同一接口在短时间内被同一用户/IP/UA多次请求或异常时, 会触发风控, 如接口返回 code 为 -352 即 风控校验失败, 同时 data 中出现 v_voucher 字段, 响应头出现 x-bili-gaia-vvoucher
v_voucher 结构为字符串 voucher_ 尾随一串以 - 为分隔符的小写 UUID
v_voucher 可用于申请 captcha 验证码, 若无意外发生, 根据验证结果使用 validate 接口获取 grisk_id 作为被风控接口的 gaia_vtoken 与 Cookie 中的 x-bili-gaia-vtoken, 即可恢复正常访问
',5)),t("p",null,[s[2]||(s[2]=e("若该情况出现在使用 Wbi 签名的接口中, 建议先检查 Wbi 签名是否正确. 若已检查 Wbi 签名或无需签名, 检查请求头中 ")),s[3]||(s[3]=t("code",null,"User-Agent",-1)),s[4]||(s[4]=e()),s[5]||(s[5]=t("code",null,"Referer",-1)),s[6]||(s[6]=e(" 是否正常, 以及 ")),s[7]||(s[7]=t("code",null,"Cookie",-1)),s[8]||(s[8]=e(" 中 ")),l(n,{to:"/docs/misc/sign/bili_ticket.html"},{default:a(()=>s[0]||(s[0]=[t("code",null,"bili_ticket",-1)])),_:1,__:[0]}),s[9]||(s[9]=e()),l(n,{to:"/docs/misc/buvid3_4.html"},{default:a(()=>s[1]||(s[1]=[t("code",null,"b_nut",-1),e(),t("code",null,"buvid3",-1),e(),t("code",null,"buvid4",-1)])),_:1,__:[1]}),s[10]||(s[10]=e(" 等是否存在. 使用 captcha 是最后的选择, 因为 captcha 验证需要用户操作"))]),s[36]||(s[36]=t("p",null,[e("参见 "),t("a",{href:"https://github.com/SocialSisterYi/bilibili-API-collect/issues/1067",target:"_blank",rel:"noopener noreferrer"},"#1067")],-1)),s[37]||(s[37]=t("p",null,[t("strong",null,"注意: 不是所有风控都可以使用本方式通过 captcha 解决")],-1)),s[38]||(s[38]=t("h2",{id:"操作流程",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#操作流程"},[t("span",null,"操作流程")])],-1)),t("ol",null,[s[28]||(s[28]=o(`快速以不正确的姿势请求接口, 直到返回 v_voucher 字段如下. 若 data 中没有 v_voucher 字段, 则检查响应头 x-bili-gaia-vvoucher
{
"code": -352,
"message": "风控校验失败",
"ttl": 1,
"data": {
"v_voucher": "voucher_84a8c3ce-33f5-4551-9552-9c6b13aa7938"
}
}
`,1)),t("li",null,[t("p",null,[s[12]||(s[12]=t("a",{href:"#%E4%BB%8E-v_voucher-%E7%94%B3%E8%AF%B7-captcha"},[e("请求 "),t("code",null,"register"),e(" 接口")],-1)),s[13]||(s[13]=e(", 请求体传入 ")),s[14]||(s[14]=t("code",null,"csrf",-1)),s[15]||(s[15]=e(" 及 ")),s[16]||(s[16]=t("code",null,"v_voucher",-1)),s[17]||(s[17]=e(", 该接口返回与 ")),l(n,{to:"/docs/login/login_action/#%E7%94%B3%E8%AF%B7captcha%E9%AA%8C%E8%AF%81%E7%A0%81"},{default:a(()=>s[11]||(s[11]=[e("申请captcha验证码")])),_:1,__:[11]}),s[18]||(s[18]=e(" 部分相同, 记录此处返回的 ")),s[19]||(s[19]=t("code",null,"token",-1)),s[20]||(s[20]=e()),s[21]||(s[21]=t("code",null,"challenge",-1))])]),t("li",null,[t("p",null,[s[23]||(s[23]=e("按照 ")),l(n,{to:"/docs/login/login_action/#%E9%AA%8C%E8%AF%81captcha%E9%AA%8C%E8%AF%81%E7%A0%81"},{default:a(()=>s[22]||(s[22]=[e("验证captcha验证码")])),_:1,__:[22]}),s[24]||(s[24]=e(" 进行验证, 记下验证结果的 ")),s[25]||(s[25]=t("code",null,"validate",-1)),s[26]||(s[26]=e(" 与 ")),s[27]||(s[27]=t("code",null,"seccode",-1))])]),s[29]||(s[29]=o('请求 validate 接口, 请求体传入 challenge token validate seccode csrf, 该接口返回 grisk_id 即 gaia_vtoken 与 x-bili-gaia-vtoken
重新请求原接口, 原 URL 参数加入 gaia_vtoken, Cookie 加入 x-bili-gaia-vtoken, 即恢复正常
',2))]),s[39]||(s[39]=t("h2",{id:"接口列表",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#接口列表"},[t("span",null,"接口列表")])],-1)),s[40]||(s[40]=t("h3",{id:"从-v-voucher-申请-captcha",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#从-v-voucher-申请-captcha"},[t("span",null,"从 v_voucher 申请 captcha")])],-1)),s[41]||(s[41]=t("blockquote",null,[t("p",null,"https://api.bilibili.com/x/gaia-vgate/v1/register")],-1)),t("p",null,[s[31]||(s[31]=e("注: 同一有效 ")),s[32]||(s[32]=t("code",null,"v_voucher",-1)),s[33]||(s[33]=e(" 只能请求一次, 请求完毕请立即 ")),l(n,{to:"/docs/login/login_action/#%E8%BF%9B%E8%A1%8C%E9%AA%8C%E8%AF%81"},{default:a(()=>s[30]||(s[30]=[e("进行验证")])),_:1,__:[30]}),s[34]||(s[34]=e(" 防止过期失效"))]),s[42]||(s[42]=o(`请求方式: POST
正文参数(application/x-www-form-urlencoded):
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|---|
| csrf | str | CSRF Token (位于 Cookie 的 bili_jct) | 非必要 | |
| v_voucher | str | v_voucher | 必要 | |
JSON回复:
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---|
| code | num | 返回值 | 0:成功 100000: 验证码获取失败 |
| message | str | 错误信息 | 默认为 0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
data 对象:
| 字段 | 类型 | 内容 | 备注 |
|---|
| type | str | 验证码类型 | 目前只有 geetest |
| token | str | 验证码 token | 用于验证 |
| geetest | obj | 极验信息 | 若为 null 则说明该风控无法通过 captcha 解除 |
| biliword | null | | |
| phone | null | | |
| sms | null | | |
geetest 对象:
| 字段 | 类型 | 内容 | 备注 |
|---|
| gt | str | 极验id | 一般为固定值 |
| challenge | str | 极验KEY | 由B站后端产生用于人机验证 |
示例:
假设此处 v_voucher 为 voucher_ecca35e6-36da-4f38-bd84-b3f420ea08c1
curl -X POST "https://api.bilibili.com/x/gaia-vgate/v1/register" \\
--data-urlencode "v_voucher=voucher_ecca35e6-36da-4f38-bd84-b3f420ea08c1"
查看响应示例:
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"type": "geetest",
"token": "e7abdb050c3d4609979f1685137e3bc0",
"geetest": {
"challenge": "85118f8714875ca4c6d5641bb0ce9ddf",
"gt": "ac597a4506fee079629df5d8b66dd4fe"
},
"biliword": null,
"phone": null,
"sms": null
}
}
https://api.bilibili.com/x/gaia-vgate/v1/validate
请求方式: POST
正文参数(application/x-www-form-urlencoded):
| 参数名 | 类型 | 内容 | 必要性 | 备注 |
|---|
| csrf | str | CSRF Token (位于 Cookie 的 bili_jct) | 非必要 | 若登陆则必要 |
| challenge | str | 验证码 challenge | 必要 | |
| token | str | 验证码 token | 必要 | |
| validate | str | 验证结果 validate | 必要 | |
| seccode | str | 验证结果 seccode | 必要 | |
JSON回复:
根对象:
| 字段 | 类型 | 内容 | 备注 |
|---|
| code | num | 返回值 | 0:成功 -111: csrf 校验失败 100003: 验证码过期 |
| message | str | 错误信息 | 默认为 0 |
| ttl | num | 1 | |
| data | obj | 信息本体 | |
data 对象:
| 字段 | 类型 | 内容 | 备注 |
|---|
| is_valid | num | 验证结果 | 1:验证成功 |
| grisk_id | str | gaia_vtoken | 用于恢复正常访问 |
示例:
curl -X POST "https://api.bilibili.com/x/gaia-vgate/v1/validate" \\
--data-urlencode "challenge=e4fcb337b8c0427b56320f97e1064210" \\
--data-urlencode "csrf=xxxxxxxxxxxxxxx" \\
--data-urlencode "seccode=360f7b9cf75c74c68fbb7475416d0e0d|jordan" \\
--data-urlencode "token=0e1e58bdff3d4b8aa298e346fed07eeb" \\
--data-urlencode "validate=360f7b9cf75c74c68fbb7475416d0e0d"
查看响应示例:
{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"is_valid": 1,
"grisk_id": "2e91cf2b67172ca8432fe7c9ab66a5c4"
}
}
`,27))])}const b=d(c,[["render",u]]),y=JSON.parse('{"path":"/docs/misc/sign/v_voucher.html","title":"v_voucher 验证","lang":"zh-CN","frontmatter":{},"git":{"updatedTime":1744996652000,"contributors":[{"name":"SessionHu","username":"SessionHu","email":"102411014+SessionHu@users.noreply.github.com","commits":3,"url":"https://github.com/SessionHu"},{"name":"SocialSisterYi","username":"SocialSisterYi","email":"45892418+SocialSisterYi@users.noreply.github.com","commits":1,"url":"https://github.com/SocialSisterYi"}],"changelog":[{"hash":"17b0e43ec2573a3b7f99d5c4c204a4f3b7f9641b","time":1744996652000,"email":"102411014+SessionHu@users.noreply.github.com","author":"SessionHu","message":"feat: add details"},{"hash":"1e24c6b1889160c4c35c01416aa4239501accf5f","time":1726759053000,"email":"102411014+SessionHu@users.noreply.github.com","author":"Session小胡","message":"调整部分接口描述与错误修复 (#1088)","coAuthors":[{"name":"社会易姐QwQ","email":"45892418+SocialSisterYi@users.noreply.github.com"}]},{"hash":"60a0c5d1a2f44fe61335da04571305fa7727a968","time":1724238159000,"email":"102411014+SessionHu@users.noreply.github.com","author":"Session小胡","message":"feat: 各种接口补充与错误修正 (#1066)"}]},"filePathRelative":"docs/misc/sign/v_voucher.md"}');export{b as comp,y as data};