openapi: 3.1.0 info: title: Login CAPTCHA policy version: 1.0.0 paths: /api/v1/ops/login-captcha-policy: get: operationId: getLoginCaptchaPolicy summary: 平台管理员查看 SaaS 和小程序验证码方式与配置就绪状态 description: 需要 operator 登录身份及 X-Tenant-ID 对应的 ops_admin 角色。配置为全平台设置,只返回模式、版本和凭据是否已加载,绝不返回密钥。 parameters: - {in: header, name: X-Tenant-ID, required: true, schema: {type: string, format: uuid}} responses: '200': description: 验证码配置 content: application/json: schema: type: object properties: ok: {type: boolean} data: {$ref: '#/components/schemas/Policy'} '403': {description: 非平台管理员} post: operationId: updateLoginCaptchaPolicy summary: 分端切换图形、拼图滑块或腾讯云验证码 description: 需要 ops_admin、X-Tenant-ID、UUID v4 X-Request-ID;使用 Cookie 时另需同源 Origin 和有效 X-CSRF-Token。使用 version 乐观锁。新配置立即生效,旧挑战失效;凭据未配置不能启用腾讯云。不自动降级。 parameters: - {in: header, name: X-Tenant-ID, required: true, schema: {type: string, format: uuid}} - {in: header, name: X-Request-ID, required: true, schema: {type: string, format: uuid}} requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [saas_mode, mini_mode, version] properties: saas_mode: {type: string, enum: [image, slide, tencent]} mini_mode: {type: string, enum: [image, tencent]} version: {type: integer, minimum: 1} responses: '200': description: 保存成功并记录审计 content: application/json: schema: type: object properties: ok: {type: boolean} data: {$ref: '#/components/schemas/Policy'} '403': {description: 非平台管理员或 CSRF 校验失败} '409': {description: 版本冲突或腾讯云配置未就绪} components: schemas: Policy: type: object required: [saas_mode, mini_mode, version, saas_configured, mini_configured] properties: saas_mode: {type: string, enum: [image, slide, tencent]} mini_mode: {type: string, enum: [image, tencent]} version: {type: integer} saas_configured: {type: boolean} mini_configured: {type: boolean} SlideCaptchaVerifyInput: type: object additionalProperties: false required: [captcha_id, x, y] description: 提交拼块左上角在原图 320×180 像素坐标系的位置;服务端核对位置及当前会话,误差最多 3 像素。一次错误即消费挑战。 properties: captcha_id: {type: string, format: uuid} x: {type: integer, minimum: 0, maximum: 268} y: {type: integer, minimum: 0, maximum: 128} SlideCaptchaVerifyResponse: type: object required: [ok, data] properties: ok: {type: boolean, const: true} code: {type: string} request_id: {type: string, format: uuid} server_time_ms: {type: integer, format: int64} data: type: object additionalProperties: false required: [captcha_id, captcha_ticket, expires_at_ms] properties: captcha_id: {type: string, format: uuid} captcha_ticket: type: string pattern: '^[A-Za-z0-9_-]{43}$' description: 仅本地校验的一次凭证,绑定当前会话、客户端、挑战与策略版本;通过既有 captcha_id/captcha_ticket 提交密码登录或短信申请。 expires_at_ms: type: integer format: int64 description: 原挑战的 2 分钟截止时间,验证成功不会延长有效期。