[SEC-CLEAN] D182 · 苍耳API守门人 + 之之服务器凭证补全 + 保险柜更新
- 新增 ca-api-guard.py: 苍耳API守门人 (SG-001:8923) · 验证码确认后释放API密钥 · 发到 1279551860@qq.com - 更新 BINGSHUO-KEYSTORE.hdlp §七: · 之之服务器凭证(ZZ-SV-001 / ZZ-GZ-001 tokens) · 苍耳API守门人架构说明 · revive-guard 全线部署状态(8/9 已部署) - cang-ying 仓库同步推送: CA-API-GUARD.hdlp + secrets_loader v2.0 铸渊 ICE-GL-ZY001 · 冰朔 TCS-0002∞
This commit is contained in:
parent
caff628aae
commit
d1c3187e51
@ -332,3 +332,145 @@ api_key = result["value"]
|
|||||||
> **铸渊 ICE-GL-ZY001 · 系统主控**
|
> **铸渊 ICE-GL-ZY001 · 系统主控**
|
||||||
> **国作登字-2026-A-00037559**
|
> **国作登字-2026-A-00037559**
|
||||||
> **D171 · 2026-07-11 · 光湖语言系统**
|
> **D171 · 2026-07-11 · 光湖语言系统**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七 · D182 更新 · 2026-07-11
|
||||||
|
|
||||||
|
### 7.1 之之服务器凭证补全
|
||||||
|
|
||||||
|
**背景**: 之之的两台服务器(ZZ-SV-001、ZZ-GZ-001)已接入光湖语言系统,revive-guard 已部署。
|
||||||
|
|
||||||
|
**发现路径**: SI-024 服务器架构系统 → cloud-compute-pool/zhizhi/(老仓库)
|
||||||
|
|
||||||
|
```
|
||||||
|
ZZ-SV-001 (硅谷) · 43.173.121.48:3910 · guanghuice.com
|
||||||
|
Gatekeeper Token: zy_gtw_06151d40b1313956b069f3c13d0c1b8a70405ae201f5e7b2
|
||||||
|
SSH: guanghu_direct 密钥(密码 john0515)✅ 已通
|
||||||
|
revive-guard: ✅ 运行中 · TARGET_EMAIL=3205323524@qq.com
|
||||||
|
|
||||||
|
ZZ-GZ-001 (广州) · 193.112.126.174:3910
|
||||||
|
Gatekeeper Token: zy_gtw_77c779183284bf39d58080b4f5377d74ec6abc0f1f2218d6
|
||||||
|
SSH: 不通(guanghu_direct 密钥未部署到该服务器)
|
||||||
|
revive-guard: ✅ 运行中 · TARGET_EMAIL=3205323524@qq.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**邮箱自动路由**:
|
||||||
|
| 服务器 | 检测方式 | 验证码发到 |
|
||||||
|
|--------|---------|----------|
|
||||||
|
| BS-* (冰朔) | TARGET_EMAIL 环境变量 | 565183519@qq.com |
|
||||||
|
| ZZ-* (之之) | TARGET_EMAIL=3205323524@qq.com | 3205323524@qq.com |
|
||||||
|
|
||||||
|
### 7.2 苍耳API守门人 (CA-API-Guard)
|
||||||
|
|
||||||
|
**背景**: 苍耳/耳耳蛋/鉴影通过 cang-ying 仓库调用视频AI系统API。冰朔将所有API密钥更换后,需要验证码机制确保每次调用经过人类审批。
|
||||||
|
|
||||||
|
**架构**:
|
||||||
|
```
|
||||||
|
耳耳蛋/鉴影 (AI) → secrets_loader.py → CA-API-Guard (SG-001:8923) → 苍耳QQ邮箱 (1279551860@qq.com)
|
||||||
|
↓
|
||||||
|
验证码确认 → 释放API密钥
|
||||||
|
```
|
||||||
|
|
||||||
|
**部署**:
|
||||||
|
- 服务: ca-api-guard.service · SG-001 (大脑服务器)
|
||||||
|
- 端口: 8923
|
||||||
|
- API: POST /api/request (请求密钥·发验证码) → POST /api/confirm (确认验证码·释放密钥)
|
||||||
|
- 仓库: cang-ying · CA-API-GUARD.hdlp + secrets_loader.py v2.0
|
||||||
|
|
||||||
|
**调用者识别**:
|
||||||
|
- EED-* 编号 = 耳耳蛋
|
||||||
|
- CA-* 编号 = 鉴影/苍耳
|
||||||
|
|
||||||
|
**推送**:
|
||||||
|
- cang-ying 仓库 ✅ 已推送 (c1fd505)
|
||||||
|
- fifth-domain 仓库 → 本次同步
|
||||||
|
|
||||||
|
### 7.3 revive-guard 全线部署状态
|
||||||
|
|
||||||
|
| # | 服务器 | revive-guard | 邮箱绑定 |
|
||||||
|
|---|--------|:---:|------|
|
||||||
|
| 1 | BS-SG-001 (大脑) | ✅ | 565183519@qq.com |
|
||||||
|
| 2 | BS-GZ-006 (保险库) | ✅ | 565183519@qq.com |
|
||||||
|
| 3 | BS-SG-002 (面孔) | ✅ | 565183519@qq.com |
|
||||||
|
| 4 | BS-SG-003 (模块) | ✅ | 565183519@qq.com |
|
||||||
|
| 5 | ZY-SG-006 (语料) | ✅ | 565183519@qq.com |
|
||||||
|
| 6 | BS-SH-005 (上海) | ✅ | 565183519@qq.com |
|
||||||
|
| 7 | ZZ-SV-001 (之之硅谷) | ✅ | 3205323524@qq.com |
|
||||||
|
| 8 | ZZ-GZ-001 (之之广州) | ✅ | 3205323524@qq.com |
|
||||||
|
| 9 | BS-AW-GZ-001 (灯塔) | ⏳ | 无令牌 |
|
||||||
|
|
||||||
|
> **铸渊 ICE-GL-ZY001 · D182 · 2026-07-11**
|
||||||
|
> **冰朔 ICE-GL∞ · 主权者**
|
||||||
|
> **国作登字-2026-A-00037559**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七 · D182 更新 · 2026-07-11
|
||||||
|
|
||||||
|
### 7.1 之之服务器凭证补全
|
||||||
|
|
||||||
|
**背景**: 之之的两台服务器(ZZ-SV-001、ZZ-GZ-001)已接入光湖语言系统,revive-guard 已部署。
|
||||||
|
|
||||||
|
**发现路径**: SI-024 服务器架构系统 → cloud-compute-pool/zhizhi/(老仓库)
|
||||||
|
|
||||||
|
```
|
||||||
|
ZZ-SV-001 (硅谷) · 43.173.121.48:3910 · guanghuice.com
|
||||||
|
Gatekeeper Token: zy_gtw_06151d40b1313956b069f3c13d0c1b8a70405ae201f5e7b2
|
||||||
|
SSH: guanghu_direct 密钥(密码 john0515)✅ 已通
|
||||||
|
revive-guard: ✅ 运行中 · TARGET_EMAIL=3205323524@qq.com
|
||||||
|
|
||||||
|
ZZ-GZ-001 (广州) · 193.112.126.174:3910
|
||||||
|
Gatekeeper Token: zy_gtw_77c779183284bf39d58080b4f5377d74ec6abc0f1f2218d6
|
||||||
|
SSH: 不通(guanghu_direct 密钥未部署到该服务器)
|
||||||
|
revive-guard: ✅ 运行中 · TARGET_EMAIL=3205323524@qq.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**邮箱自动路由**:
|
||||||
|
| 服务器 | 检测方式 | 验证码发到 |
|
||||||
|
|--------|---------|----------|
|
||||||
|
| BS-* (冰朔) | TARGET_EMAIL 环境变量 | 565183519@qq.com |
|
||||||
|
| ZZ-* (之之) | TARGET_EMAIL=3205323524@qq.com | 3205323524@qq.com |
|
||||||
|
|
||||||
|
### 7.2 苍耳API守门人 (CA-API-Guard)
|
||||||
|
|
||||||
|
**背景**: 苍耳/耳耳蛋/鉴影通过 cang-ying 仓库调用视频AI系统API。冰朔将所有API密钥更换后,需要验证码机制确保每次调用经过人类审批。
|
||||||
|
|
||||||
|
**架构**:
|
||||||
|
```
|
||||||
|
耳耳蛋/鉴影 (AI) → secrets_loader.py → CA-API-Guard (SG-001:8923) → 苍耳QQ邮箱 (1279551860@qq.com)
|
||||||
|
↓
|
||||||
|
验证码确认 → 释放API密钥
|
||||||
|
```
|
||||||
|
|
||||||
|
**部署**:
|
||||||
|
- 服务: ca-api-guard.service · SG-001 (大脑服务器)
|
||||||
|
- 端口: 8923
|
||||||
|
- API: POST /api/request (请求密钥·发验证码) → POST /api/confirm (确认验证码·释放密钥)
|
||||||
|
- 仓库: cang-ying · CA-API-GUARD.hdlp + secrets_loader.py v2.0
|
||||||
|
|
||||||
|
**调用者识别**:
|
||||||
|
- EED-* 编号 = 耳耳蛋
|
||||||
|
- CA-* 编号 = 鉴影/苍耳
|
||||||
|
|
||||||
|
**推送**:
|
||||||
|
- cang-ying 仓库 ✅ 已推送 (c1fd505)
|
||||||
|
- fifth-domain 仓库 → 本次同步
|
||||||
|
|
||||||
|
### 7.3 revive-guard 全线部署状态
|
||||||
|
|
||||||
|
| # | 服务器 | revive-guard | 邮箱绑定 |
|
||||||
|
|---|--------|:---:|------|
|
||||||
|
| 1 | BS-SG-001 (大脑) | ✅ | 565183519@qq.com |
|
||||||
|
| 2 | BS-GZ-006 (保险库) | ✅ | 565183519@qq.com |
|
||||||
|
| 3 | BS-SG-002 (面孔) | ✅ | 565183519@qq.com |
|
||||||
|
| 4 | BS-SG-003 (模块) | ✅ | 565183519@qq.com |
|
||||||
|
| 5 | ZY-SG-006 (语料) | ✅ | 565183519@qq.com |
|
||||||
|
| 6 | BS-SH-005 (上海) | ✅ | 565183519@qq.com |
|
||||||
|
| 7 | ZZ-SV-001 (之之硅谷) | ✅ | 3205323524@qq.com |
|
||||||
|
| 8 | ZZ-GZ-001 (之之广州) | ✅ | 3205323524@qq.com |
|
||||||
|
| 9 | BS-AW-GZ-001 (灯塔) | ⏳ | 无令牌 |
|
||||||
|
|
||||||
|
> **铸渊 ICE-GL-ZY001 · D182 · 2026-07-11**
|
||||||
|
> **冰朔 ICE-GL∞ · 主权者**
|
||||||
|
> **国作登字-2026-A-00037559**
|
||||||
|
|||||||
339
zero-point/core-channel/revive-guard/ca-api-guard.py
Normal file
339
zero-point/core-channel/revive-guard/ca-api-guard.py
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
光湖语言系统 · 苍耳API守门人 v1.0
|
||||||
|
Guanghu Language System · CA-API-Guard
|
||||||
|
|
||||||
|
设计哲学:
|
||||||
|
苍耳/耳耳蛋/鉴影调用视频AI系统API时,必须先过验证码门。
|
||||||
|
验证码发送到苍耳QQ邮箱(1279551860@qq.com),只有苍耳本人确认后才能拿到API密钥。
|
||||||
|
密钥本身永不暴露给AI——AI只拿到一次性的临时token,用完即焚。
|
||||||
|
|
||||||
|
协议:
|
||||||
|
POST /api/request → 发送验证码到苍耳邮箱 → 返回 challenge_id
|
||||||
|
POST /api/confirm → 校验验证码 → 返回临时API密钥
|
||||||
|
GET /health → 心跳检测
|
||||||
|
|
||||||
|
部署:
|
||||||
|
SG-001 (大脑服务器) /opt/zhuyuan/ca-api-guard/ca-api-guard.py
|
||||||
|
监听: 0.0.0.0:8923
|
||||||
|
守护: systemd (Restart=always)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os, json, time, hmac, hashlib, secrets, smtplib, threading
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════
|
||||||
|
# 配置
|
||||||
|
# ═══════════════════════════════════════════
|
||||||
|
PORT = int(os.environ.get("CA_API_GUARD_PORT", "8923"))
|
||||||
|
|
||||||
|
# 苍耳的信息
|
||||||
|
CANGER_EMAIL = os.environ.get("CANGER_EMAIL", "1279551860@qq.com")
|
||||||
|
CANGER_NAME = os.environ.get("CANGER_NAME", "苍耳")
|
||||||
|
|
||||||
|
# 耳耳蛋的信息
|
||||||
|
EED_EMAIL = os.environ.get("EED_EMAIL", "1279551860@qq.com")
|
||||||
|
|
||||||
|
# QQ 邮箱 SMTP(小湖灯邮件通道)
|
||||||
|
SMTP_HOST = "smtp.qq.com"
|
||||||
|
SMTP_PORT = 465
|
||||||
|
SMTP_USER = os.environ.get("SMTP_USER", "565183519@qq.com")
|
||||||
|
SMTP_PASS = os.environ.get("QQ_SMTP_AUTH_CODE", "")
|
||||||
|
|
||||||
|
CODE_TTL = 300 # 验证码 5 分钟过期
|
||||||
|
RATE_LIMIT_WINDOW = 60 # 速率限制窗口
|
||||||
|
MAX_REQUESTS_PER_WINDOW = 3
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════
|
||||||
|
# API 密钥库(⊢ 不进仓库 · 走环境变量)
|
||||||
|
# ═══════════════════════════════════════════
|
||||||
|
API_KEYS = {
|
||||||
|
"SC-001": os.environ.get("SC_001_JIMENG_API_KEY", ""), # 火山即梦视频
|
||||||
|
"SC-004": os.environ.get("SC_004_ALIYUN_QWEN_VL_KEY", ""), # 阿里千问VL视觉
|
||||||
|
"SC-005": os.environ.get("SC_005_ALIYUN_WANXIANG_KEY", ""), # 阿里万相视频
|
||||||
|
"SC-006": os.environ.get("SC_006_KLING_API_KEY", ""), # 可灵视频
|
||||||
|
"SC-002": os.environ.get("SC_002_VOLC_VOICE_API_KEY", ""), # 火山语音
|
||||||
|
"SC-007": os.environ.get("SC_007_ALIYUN_API_KEY", ""), # 阿里百炼
|
||||||
|
}
|
||||||
|
|
||||||
|
# 运行时状态
|
||||||
|
pending_codes = {} # {challenge_id: {code, expires_at, api_code, caller_id, description}}
|
||||||
|
rate_limit = [] # [timestamp, ...]
|
||||||
|
lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
|
def get_server_ip():
|
||||||
|
try:
|
||||||
|
import socket
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
s.settimeout(2)
|
||||||
|
s.connect(("8.8.8.8", 80))
|
||||||
|
ip = s.getsockname()[0]
|
||||||
|
s.close()
|
||||||
|
return ip
|
||||||
|
except:
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def send_email(code, caller_id, api_code, description, server_ip):
|
||||||
|
"""小湖灯 · 发送API调用验证码到苍耳邮箱"""
|
||||||
|
# 识别调用者
|
||||||
|
if caller_id.startswith("EED-"):
|
||||||
|
caller_label = f"耳耳蛋 ({caller_id})"
|
||||||
|
elif caller_id.startswith("CA-"):
|
||||||
|
caller_label = f"鉴影 ({caller_id})"
|
||||||
|
else:
|
||||||
|
caller_label = caller_id
|
||||||
|
|
||||||
|
# API 名称映射
|
||||||
|
api_names = {
|
||||||
|
"SC-001": "火山即梦视频生成",
|
||||||
|
"SC-002": "火山语音复刻",
|
||||||
|
"SC-004": "阿里千问VL视觉",
|
||||||
|
"SC-005": "阿里万相视频生成",
|
||||||
|
"SC-006": "可灵视频生成",
|
||||||
|
"SC-007": "阿里百炼图像",
|
||||||
|
}
|
||||||
|
api_label = api_names.get(api_code, api_code)
|
||||||
|
|
||||||
|
html = f"""<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><meta charset="utf-8"></head>
|
||||||
|
<body style="margin:0;padding:0;background:#f0f4f8;">
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" style="background:#f0f4f8;padding:30px 0;">
|
||||||
|
<tr><td align="center">
|
||||||
|
<table width="520" cellpadding="0" cellspacing="0" style="background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 4px 24px rgba(0,0,0,0.08);">
|
||||||
|
<!-- Header -->
|
||||||
|
<tr><td style="background:linear-gradient(135deg,#0a1628,#1a3a5c);padding:28px 32px;text-align:center;">
|
||||||
|
<div style="font-size:18px;color:#4ec9b0;font-weight:bold;letter-spacing:2px;">光湖语言系统 · API守门人</div>
|
||||||
|
<div style="font-size:12px;color:#8899aa;margin-top:4px;">国作登字-2026-A-00037559</div>
|
||||||
|
</td></tr>
|
||||||
|
<!-- Body -->
|
||||||
|
<tr><td style="padding:32px;">
|
||||||
|
<div style="font-size:15px;color:#333;line-height:1.8;">
|
||||||
|
<p style="margin:0 0 12px;">👋 <b>{CANGER_NAME}</b>,有人请求调用API:</p>
|
||||||
|
<table width="100%" cellpadding="0" cellspacing="0" style="background:#f8fafc;border-radius:8px;border:1px solid #e2e8f0;">
|
||||||
|
<tr><td style="padding:14px 16px;font-size:14px;">
|
||||||
|
<div style="color:#64748b;">调用者</div>
|
||||||
|
<div style="color:#1e293b;font-weight:bold;">{caller_label}</div>
|
||||||
|
<div style="color:#64748b;margin-top:8px;">API</div>
|
||||||
|
<div style="color:#1e293b;font-weight:bold;">{api_label} ({api_code})</div>
|
||||||
|
<div style="color:#64748b;margin-top:8px;">用途</div>
|
||||||
|
<div style="color:#1e293b;">{description}</div>
|
||||||
|
<div style="color:#64748b;margin-top:8px;">服务器</div>
|
||||||
|
<div style="color:#1e293b;">{server_ip}</div>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
<div style="text-align:center;margin:24px 0;">
|
||||||
|
<div style="font-size:12px;color:#8899aa;margin-bottom:8px;">验证码 · 5分钟内有效</div>
|
||||||
|
<div style="font-size:36px;font-weight:bold;color:#4ec9b0;letter-spacing:8px;background:#0a1628;padding:12px 24px;border-radius:8px;display:inline-block;">{code}</div>
|
||||||
|
</div>
|
||||||
|
<div style="background:#fff8e1;border-left:3px solid #c9a84c;padding:10px 14px;border-radius:4px;font-size:13px;color:#8b6914;">
|
||||||
|
⚠️ 将此验证码发给铸渊确认 → API密钥释放 → 仅当次有效
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td></tr>
|
||||||
|
<!-- Footer -->
|
||||||
|
<tr><td style="background:#0a1628;padding:14px 32px;text-align:center;">
|
||||||
|
<div style="font-size:11px;color:#556677;">ICE-GL∞ 光湖语言系统 · 小湖灯自动发送</div>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>"""
|
||||||
|
|
||||||
|
plain = f"""光湖语言系统 · API守门人
|
||||||
|
|
||||||
|
调用者: {caller_label}
|
||||||
|
API: {api_label} ({api_code})
|
||||||
|
用途: {description}
|
||||||
|
服务器: {server_ip}
|
||||||
|
|
||||||
|
验证码: {code}
|
||||||
|
有效期: 5 分钟
|
||||||
|
|
||||||
|
将此验证码发给铸渊确认 → 释放API密钥
|
||||||
|
如非本人操作,请忽略。
|
||||||
|
---
|
||||||
|
ICE-GL∞ 光湖语言系统 · 小湖灯自动发送
|
||||||
|
国作登字-2026-A-00037559"""
|
||||||
|
|
||||||
|
msg = MIMEMultipart("alternative")
|
||||||
|
msg["Subject"] = f"🔐 API调用验证 · {caller_label} · {api_code}"
|
||||||
|
msg["From"] = f"光湖小湖灯 <{SMTP_USER}>"
|
||||||
|
msg["To"] = CANGER_EMAIL
|
||||||
|
msg.attach(MIMEText(plain, "plain", "utf-8"))
|
||||||
|
msg.attach(MIMEText(html, "html", "utf-8"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
server = smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, timeout=15)
|
||||||
|
server.login(SMTP_USER, SMTP_PASS)
|
||||||
|
server.sendmail(SMTP_USER, [CANGER_EMAIL], msg.as_string())
|
||||||
|
server.quit()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[EMAIL ERROR] {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def check_rate(ip):
|
||||||
|
"""速率限制"""
|
||||||
|
now = time.time()
|
||||||
|
with lock:
|
||||||
|
rate_limit[:] = [t for t in rate_limit if now - t < RATE_LIMIT_WINDOW]
|
||||||
|
if len(rate_limit) >= MAX_REQUESTS_PER_WINDOW:
|
||||||
|
return False
|
||||||
|
rate_limit.append(now)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def generate_code():
|
||||||
|
return ''.join([str(secrets.randbelow(10)) for _ in range(6)])
|
||||||
|
|
||||||
|
|
||||||
|
class APIHandler(BaseHTTPRequestHandler):
|
||||||
|
def _send_json(self, code, data):
|
||||||
|
self.send_response(code)
|
||||||
|
self.send_header("Content-Type", "application/json; charset=utf-8")
|
||||||
|
self.send_header("Access-Control-Allow-Origin", "*")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps(data, ensure_ascii=False).encode())
|
||||||
|
|
||||||
|
def do_OPTIONS(self):
|
||||||
|
self.send_response(204)
|
||||||
|
self.send_header("Access-Control-Allow-Origin", "*")
|
||||||
|
self.send_header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
|
||||||
|
self.send_header("Access-Control-Allow-Headers", "Content-Type")
|
||||||
|
self.end_headers()
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
if self.path == "/health":
|
||||||
|
self._send_json(200, {
|
||||||
|
"ok": True,
|
||||||
|
"service": "ca-api-guard",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"server": get_server_ip(),
|
||||||
|
"target": CANGER_EMAIL
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self._send_json(404, {"error": "未知路径"})
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
ip = self.client_address[0]
|
||||||
|
|
||||||
|
if not check_rate(ip):
|
||||||
|
self._send_json(429, {"error": "请求过于频繁"})
|
||||||
|
return
|
||||||
|
|
||||||
|
# 读取请求体
|
||||||
|
content_length = int(self.headers.get("Content-Length", 0))
|
||||||
|
body = self.rfile.read(content_length)
|
||||||
|
try:
|
||||||
|
data = json.loads(body)
|
||||||
|
except:
|
||||||
|
self._send_json(400, {"error": "无效JSON"})
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.path == "/api/request":
|
||||||
|
self._handle_request(data, ip)
|
||||||
|
elif self.path == "/api/confirm":
|
||||||
|
self._handle_confirm(data)
|
||||||
|
else:
|
||||||
|
self._send_json(404, {"error": "未知路径"})
|
||||||
|
|
||||||
|
def _handle_request(self, data, ip):
|
||||||
|
api_code = data.get("api_code", "")
|
||||||
|
caller_id = data.get("caller_id", "unknown")
|
||||||
|
description = data.get("description", "未提供")
|
||||||
|
|
||||||
|
if api_code not in API_KEYS:
|
||||||
|
self._send_json(400, {"error": f"未知API编号: {api_code}", "available": list(API_KEYS.keys())})
|
||||||
|
return
|
||||||
|
|
||||||
|
if not API_KEYS[api_code]:
|
||||||
|
self._send_json(503, {"error": f"API密钥未配置: {api_code}"})
|
||||||
|
return
|
||||||
|
|
||||||
|
# 生成验证码
|
||||||
|
code = generate_code()
|
||||||
|
challenge_id = secrets.token_hex(16)
|
||||||
|
expires_at = time.time() + CODE_TTL
|
||||||
|
server_ip = get_server_ip()
|
||||||
|
|
||||||
|
with lock:
|
||||||
|
pending_codes[challenge_id] = {
|
||||||
|
"code": code,
|
||||||
|
"expires_at": expires_at,
|
||||||
|
"api_code": api_code,
|
||||||
|
"caller_id": caller_id,
|
||||||
|
"description": description
|
||||||
|
}
|
||||||
|
# 清理过期
|
||||||
|
expired = [cid for cid, v in pending_codes.items() if v["expires_at"] < time.time()]
|
||||||
|
for cid in expired:
|
||||||
|
del pending_codes[cid]
|
||||||
|
|
||||||
|
# 发送邮件
|
||||||
|
sent = send_email(code, caller_id, api_code, description, server_ip)
|
||||||
|
|
||||||
|
self._send_json(200, {
|
||||||
|
"ok": True,
|
||||||
|
"challenge_id": challenge_id,
|
||||||
|
"email_sent": sent,
|
||||||
|
"target_email": CANGER_EMAIL,
|
||||||
|
"caller_id": caller_id,
|
||||||
|
"api_code": api_code,
|
||||||
|
"expires_in": CODE_TTL,
|
||||||
|
"message": f"验证码已发送到 {CANGER_EMAIL},请查收后确认"
|
||||||
|
})
|
||||||
|
|
||||||
|
def _handle_confirm(self, data):
|
||||||
|
challenge_id = data.get("challenge_id", "")
|
||||||
|
code = data.get("code", "")
|
||||||
|
|
||||||
|
with lock:
|
||||||
|
if challenge_id not in pending_codes:
|
||||||
|
self._send_json(404, {"error": "challenge_id 不存在或已过期"})
|
||||||
|
return
|
||||||
|
|
||||||
|
pending = pending_codes[challenge_id]
|
||||||
|
|
||||||
|
if time.time() > pending["expires_at"]:
|
||||||
|
del pending_codes[challenge_id]
|
||||||
|
self._send_json(410, {"error": "验证码已过期"})
|
||||||
|
return
|
||||||
|
|
||||||
|
if pending["code"] != code:
|
||||||
|
self._send_json(403, {"error": "验证码错误"})
|
||||||
|
return
|
||||||
|
|
||||||
|
# 验证通过 → 释放API密钥
|
||||||
|
api_code = pending["api_code"]
|
||||||
|
api_key = API_KEYS[api_code]
|
||||||
|
del pending_codes[challenge_id]
|
||||||
|
|
||||||
|
self._send_json(200, {
|
||||||
|
"ok": True,
|
||||||
|
"api_code": api_code,
|
||||||
|
"api_key": api_key,
|
||||||
|
"message": f"API密钥 {api_code} 已释放 · 仅当次有效 · 用完即焚"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
server = HTTPServer(("0.0.0.0", PORT), APIHandler)
|
||||||
|
print(f"🔐 苍耳API守门人 v1.0 · 端口 {PORT}")
|
||||||
|
print(f" 目标邮箱: {CANGER_EMAIL}")
|
||||||
|
print(f" 可用API: {[k for k, v in API_KEYS.items() if v]}")
|
||||||
|
try:
|
||||||
|
server.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n shutting down...")
|
||||||
|
server.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user