baijiahao-cookie-validation.md 5.3 KB

百家号 Cookie 验证改进

改进内容

将百家号的 Cookie 验证从浏览器检查改为 API 接口检查,提高验证的准确性和效率。

API 接口

接口地址https://baijiahao.baidu.com/builder/app/appinfo

请求方法:GET

请求头

Cookie: <账号的 Cookie 字符串>
Referer: https://baijiahao.baidu.com/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...

返回值格式

成功响应(Cookie 有效)

{
  "errno": 0,
  "errmsg": "success",
  "data": {
    "user": {
      "app_id": 1833101008440434,
      "name": "三千痴缠坠花湮",
      "userid": 441651849,
      "status": "audit",
      "avatar": "//pic.rmb.bdstatic.com/...",
      ...
    }
  }
}

失败响应(Cookie 无效)

{
  "errno": 110,
  "errmsg": "未登录",
  "data": null
}

验证逻辑

1. 判断 Cookie 有效的条件

Cookie 被认为有效,需要同时满足以下条件:

  1. errno 为 0:表示请求成功
  2. 有用户信息data.user.namedata.user.app_id 存在
  3. 用户状态正常data.user.statusauditpassactive 或不存在

2. 判断 Cookie 无效的情况

以下情况表示 Cookie 无效:

  1. errno 非 0

    • errno: 110 - 未登录
    • 其他非 0 值 - 权限问题或其他错误
  2. errno 为 0 但没有用户信息

    • 请求成功但返回的 data.user 为空
    • 可能是 Cookie 部分失效
  3. 用户状态异常

    • status: 'banned' - 账号被封禁
    • 其他异常状态

代码实现

配置(server/src/services/HeadlessBrowserService.ts

baijiahao: {
  checkUrl: 'https://baijiahao.baidu.com/builder/app/appinfo',
  isValidResponse: (data: unknown) => {
    const resp = data as { 
      errno?: number; 
      errmsg?: string;
      data?: { 
        user?: { 
          name?: string; 
          app_id?: string | number;
          status?: string;
        } 
      } 
    };
    
    // errno 为 0 表示请求成功
    const isErrnoOk = resp?.errno === 0;
    
    // 必须有用户信息
    const hasUserInfo = !!(resp?.data?.user?.name || resp?.data?.user?.app_id);
    
    // 用户状态正常
    const userStatus = resp?.data?.user?.status;
    const isStatusOk = !userStatus || 
                       userStatus === 'audit' || 
                       userStatus === 'pass' || 
                       userStatus === 'active';
    
    return isErrnoOk && hasUserInfo && isStatusOk;
  },
}

错误处理

if (platform === 'baijiahao') {
  const errno = (data as { errno?: number })?.errno;
  
  if (errno === 0) {
    // 请求成功,但可能没有用户信息
    if (!isValid) {
      logger.warn('Baijiahao errno=0 but no user info');
      return false;
    }
    return true;
  }
  
  // errno 非 0,Cookie 无效
  logger.warn(`Baijiahao errno=${errno}, cookie invalid`);
  return false;
}

优势

1. 更快的验证速度

  • API 请求比浏览器检查快得多
  • 不需要启动无头浏览器
  • 减少资源消耗

2. 更准确的判断

  • 直接从 API 获取用户信息
  • 避免浏览器重定向的不确定性
  • 可以获取详细的错误信息

3. 更好的错误处理

  • 根据 errno 判断具体的错误类型
  • 可以区分"未登录"和"权限不足"
  • 提供更详细的日志信息

测试方法

1. 测试有效的 Cookie

curl 'https://baijiahao.baidu.com/builder/app/appinfo' \
  -H 'Cookie: BDUSS=xxx; STOKEN=xxx; ...' \
  -H 'Referer: https://baijiahao.baidu.com/'

预期结果

{
  "errno": 0,
  "data": {
    "user": {
      "name": "账号名称",
      "app_id": 123456
    }
  }
}

2. 测试无效的 Cookie

curl 'https://baijiahao.baidu.com/builder/app/appinfo' \
  -H 'Cookie: BDUSS=invalid; STOKEN=invalid;' \
  -H 'Referer: https://baijiahao.baidu.com/'

预期结果

{
  "errno": 110,
  "errmsg": "未登录"
}

常见错误码

errno 含义 处理方式
0 成功 检查是否有用户信息
110 未登录 Cookie 无效,需要重新登录
其他 其他错误 Cookie 可能无效或权限不足

日志示例

成功验证

[Baijiahao] API response: errno=0, errmsg=success, user.name=三千痴缠坠花湮, user.app_id=1833101008440434, user.status=audit
API check cookie for baijiahao: valid=true, statusCode=0

失败验证

[Baijiahao] API response: errno=110, errmsg=未登录, user.name=undefined, user.app_id=undefined, user.status=undefined
[Baijiahao] Cookie invalid: errno=110, hasUserInfo=false, status=undefined
[API] Baijiahao errno=110, cookie is invalid
API check cookie for baijiahao: valid=false, statusCode=110

注意事项

  1. 网络错误处理:如果 API 请求失败(网络错误),不应该判定为 Cookie 无效
  2. 超时处理:API 请求应该设置合理的超时时间
  3. 重试机制:对于网络错误,可以考虑重试
  4. 日志记录:记录详细的请求和响应信息,便于调试

后续优化

  1. 缓存验证结果:避免频繁请求 API
  2. 批量验证:支持一次验证多个账号
  3. 异步验证:在后台定期验证所有账号的 Cookie
  4. 提前预警:在 Cookie 即将过期时提醒用户