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('

v_voucher 验证

简述

当同一接口在短时间内被同一用户/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_idgaia_vtokenx-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):

    参数名类型内容必要性备注
    csrfstrCSRF Token (位于 Cookie 的 bili_jct)非必要
    v_voucherstrv_voucher必要

    JSON回复:

    根对象:

    字段类型内容备注
    codenum返回值0:成功
    100000: 验证码获取失败
    messagestr错误信息默认为 0
    ttlnum1
    dataobj信息本体

    data 对象:

    字段类型内容备注
    typestr验证码类型目前只有 geetest
    tokenstr验证码 token用于验证
    geetestobj极验信息若为 null 则说明该风控无法通过 captcha 解除
    biliwordnull
    phonenull
    smsnull

    geetest 对象:

    字段类型内容备注
    gtstr极验id一般为固定值
    challengestr极验KEY由B站后端产生用于人机验证

    示例:

    假设此处 v_vouchervoucher_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
      }
    }

    从验证结果获取 grisk_id

    https://api.bilibili.com/x/gaia-vgate/v1/validate

    请求方式: POST

    正文参数(application/x-www-form-urlencoded):

    参数名类型内容必要性备注
    csrfstrCSRF Token (位于 Cookie 的 bili_jct)非必要若登陆则必要
    challengestr验证码 challenge必要
    tokenstr验证码 token必要
    validatestr验证结果 validate必要
    seccodestr验证结果 seccode必要

    JSON回复:

    根对象:

    字段类型内容备注
    codenum返回值0:成功
    -111: csrf 校验失败
    100003: 验证码过期
    messagestr错误信息默认为 0
    ttlnum1
    dataobj信息本体

    data 对象:

    字段类型内容备注
    is_validnum验证结果1:验证成功
    grisk_idstrgaia_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};