认证自动化¶
1. 密码传输格式¶
结论: 前端传明文,后端用 bcrypt 验证
// frontend/src/pages/login.tsx:85-88 — 前端密码传输
await apiRequest('v1UsersPasswordLoginCreate', {
email: userEmail.trim(),
password: userPassword.trim(), // 直接传用户输入的明文
captcha_token: token,
})
// backend/pkg/crypto/bcrypt.go:22-24 — 后端密码验证
func VerifyPassword(dbPassword, password string) error {
return bcrypt.CompareHashAndPassword([]byte(dbPassword), []byte(password))
}
注释错误: 后端 domain 注释标注的 "MD5加密后的值" 是过时的错误注释,源自 Swagger 自动生成时的初始模板。实际密码以明文在 HTTPS 中传输,后端用 bcrypt 验证。
对账号池的影响: 账号池需存储明文密码,登录时直接传明文。
2. 验证码自动化评估¶
MonkeyCode 登录页面使用 CAP.js/go-cap 验证码系统:
验证码生成:
前端加载 CAP.js → 生成 50×32 网格图像(识别难度: 中等)
→ 提交 grid_id + grid_positions → 后端验证
验证码参数:
网格大小: 50×32 像素
类型: 图片网格选择(选择包含特定物体的格子)
TTL: 验证码 token 5 分钟有效
| 方案 | 可行性 | 成本 | 说明 |
|---|---|---|---|
| Cookie 复用 | ★★★★★ | 极低 | 最推荐,完全绕过验证码 |
| 多模态 LLM 识别 | ★★★☆☆ | 中等 | 50x32 网格识别,GPT-4V 可尝试 |
| 第三方验证码服务 | ★★★☆☆ | 中等 | 使用专业验证码识别服务 |
推荐方案: 浏览器 Cookie 复用 + 自动保活。如需全自动登录,使用多模态 LLM 识别验证码图片。
# 验证码识别示例(使用 GPT-4V)
import base64
from openai import OpenAI
def solve_captcha(grid_image_base64: str) -> list:
"""使用多模态 LLM 识别 CAP.js 验证码网格"""
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "识别这个验证码网格中包含特定物体的格子位置,返回格子序号列表"},
{"type": "image_url", "image_url": {
"url": f"data:image/png;base64,{grid_image_base64}"
}}
]
}
]
)
return parse_grid_positions(response.choices[0].message.content)
3. Session 保活协议¶
有效性检测¶
# 检查 Session 是否有效
curl -s https://api.monkeycode-ai.com/api/v1/users/status \
-H "Cookie: monkeycode_ai_session={uuid}" | jq .
code: 0→ session 有效code: 40100→ session 失效
重要发现: Status 端点不刷新 TTL¶
Status 端点和 Auth 中间件都不刷新 Redis TTL。Session 从创建时起固定 30 天过期,任何 API 调用都无法延长。
// backend/middleware/auth.go — Auth 中间件(不刷新 TTL)
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
session := session.Get[SessionData](c, cookieName)
if session == nil {
c.AbortWithStatusJSON(401, ErrorResponse{Code: 40100, Msg: "unauthorized"})
return
}
// 注意:这里没有调用 session.RefreshTTL()
// 即使调用了 API,TTL 也不会延长
c.Set("user", session.UserID)
c.Next()
}
}
| 操作 | 是否刷新 TTL |
|---|---|
| 登录(Save) | ✅ 设置 30 天 |
| 调用 Status | ❌ 不刷新 |
| 调用任何 API | ❌ 不刷新 |
| Auth 中间件 | ❌ 不刷新 |
| TargetActive | ❌ 不刷新 |
自动保活策略¶
# 建议的 Session 自动保活策略
import time
from datetime import datetime, timedelta
class SessionKeeper:
"""Session 自动保活管理器"""
def __init__(self, session_cookie: str, created_at: datetime):
self.session = session_cookie
self.created_at = created_at
self.expires_at = created_at + timedelta(days=30)
def days_remaining(self) -> int:
return (self.expires_at - datetime.now()).days
def should_renew(self) -> bool:
"""当剩余不足 3 天时,需要重新登录"""
return self.days_remaining() < 3
def renew_session(self):
"""重新登录获取新 Session"""
# 每次登录获得 30 天有效期
# 建议: 当剩余 3 天时触发重新登录
pass
# 使用示例
keeper = SessionKeeper(
session_cookie="monkeycode_ai_session=xxx",
created_at=datetime.now()
)
# 每 24 小时检查一次
while True:
if keeper.should_renew():
print(f"Session 剩余 {keeper.days_remaining()} 天,需要重新登录")
# 执行登录流程获取新 Session
break
time.sleep(24 * 3600)
4. 并发 Session 策略¶
| 策略 | 说明 | 风险 | 适用场景 |
|---|---|---|---|
| 单 session 串行 | 每账号 1 个 session,每次 1 个请求 | 低风险,吞吐量低 | 个人使用 |
| 多 session 并发 | 每账号 2+ session 同时使用 | 中风险,开源代码无限制 | 小型号池 |
| 推荐: 1 主 1 备 | 主 API + WS,备切换 | 风险可控 | 推荐方案 |
// 号池的 Session 分配策略(account-pool.ts 模式)
interface AccountSession {
primary: string; // 主 Session(用于 API + WS)
backup: string; // 备用 Session(用于切换)
lastUsed: number;
taskCount: number;
}
// 并发策略: 每个账号最多 2 个并发 session
// 但每个 session 只能有 1 个活跃任务(TaskFlow 限制)
5. 登录错误码¶
| HTTP 状态码 | Code | 含义 | 触发条件 |
|---|---|---|---|
| 200 | 0 | 登录成功 | 账号密码正确,验证码通过 |
| 400 | 10001 | 参数错误 | 缺少 email/password/captcha_token |
| 401 | 40100 | 未授权/Session 过期 | Session 不存在或已过期 |
| 401 | 40101 | 账号或密码错误 | bcrypt 验证失败 |
| 401 | 40102 | 验证码错误 | captcha_token 无效或已过期 |
| 403 | 40300 | 账号被禁用 | 用户状态为 "banded" |
附录:逆向分析代码示例¶
附录 A: 快速 Session 有效性检查 (curl)¶
# 批量检查 Session 有效性
for cookie in "session1=xxx" "session2=yyy" "session3=zzz"; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
https://api.monkeycode-ai.com/api/v1/users/status \
-H "Cookie: monkeycode_ai_session=$cookie")
echo "Session $cookie: HTTP $status"
done
# 期望输出:
# Session session1=xxx: HTTP 200 (有效)
# Session session2=yyy: HTTP 401 (失效)
附录 B: 密码明文传输验证 (Python 测试)¶
# 验证 MonkeyCode 的密码传输是明文而非 MD5
import requests
from urllib.parse import parse_qs
# 假设的登录场景 — 抓包验证密码传输格式
login_url = "https://api.monkeycode-ai.com/api/v1/users/password-login"
payload = {
"email": "test@example.com",
"password": "明文密码ABC123!",
"captcha_token": "captcha_xxx"
}
# 密码是明文直接传输
resp = requests.post(login_url, json=payload)
# 如果密码是 MD5,payload 应该包含 md5 字符串
# 但实际传输的是原始密码字符串
assert "明文密码" in resp.request.body.decode() # 验证明文
print("✅ 密码以明文形式在 HTTPS 中传输")
相关章节¶
- Session 存储机制 — Redis 数据结构
- 验证码系统 — CAP.js/go-cap 详情
- 认证号池差距分析 — 完整差距分析