update: smtp 验证码有效期 60s 调整为 10 分钟,邮件正文从 CODE_TTL 派生
60 秒对邮件送达延迟过于紧张;正文有效期文案改为按 TTL 自动生成避免漂移,前端提示与 README 同步。同时移除 .env 排查用的凭证明文调试打印。
This commit is contained in:
1 parent
f5b69d0b4c
commit
f4a7aca2fa
5 files changed
+8
-11
No files matched your search
@@ -136,7 +136,7 @@
|
|||||||
### smtp(邮件服务)
|
### smtp(邮件服务)
|
||||||
|
|
||||||
- 注册流程的邮箱验证码后端,基于 pymsg(MsgServer,TCP 长度前缀帧 + JSON),监听 127.0.0.1:8008。
|
- 注册流程的邮箱验证码后端,基于 pymsg(MsgServer,TCP 长度前缀帧 + JSON),监听 127.0.0.1:8008。
|
||||||
- pymsg 路由:`send_email`(生成 6 位验证码并经 SMTP_SSL 发送,60 秒有效,发送失败自动作废)、`verify_email`(校验,通过即一次性消费防重放,兼容旧字段 `input_captcha`)、`health`。
|
- pymsg 路由:`send_email`(生成 6 位验证码并经 SMTP_SSL 发送,10 分钟有效,发送失败自动作废)、`verify_email`(校验,通过即一次性消费防重放,兼容旧字段 `input_captcha`)、`health`。
|
||||||
- 验证码存于进程内存(锁保护 + 惰性过期清理),SMTP 账号通过 `.env` 配置(`SMTP_SERVER` / `SMTP_PORT` / `SMTP_USER` / `__PASSWORD`,`__PASSWORD` 兼容别名 `SMTP_PASSWORD`)。
|
- 验证码存于进程内存(锁保护 + 惰性过期清理),SMTP 账号通过 `.env` 配置(`SMTP_SERVER` / `SMTP_PORT` / `SMTP_USER` / `__PASSWORD`,`__PASSWORD` 兼容别名 `SMTP_PASSWORD`)。
|
||||||
|
|
||||||
### aibox(独立 AI 智能体系统)
|
### aibox(独立 AI 智能体系统)
|
||||||
|
|||||||
+2
-2
@@ -9,7 +9,7 @@ UniServe Framework 的应用层网关,C++20 实现。
|
|||||||
- **账号鉴权**:`/register` 注册(需邮箱验证码,经 pymsg 调 smtp:8008 校验)、`/login` 登录,签发 RSA 签名的 Token。
|
- **账号鉴权**:`/register` 注册(需邮箱验证码,经 pymsg 调 smtp:8008 校验)、`/login` 登录,签发 RSA 签名的 Token。
|
||||||
- **反向代理**:携带 Token 的请求校验后转发到 `Proxy.opened` 中放开的内部服务。
|
- **反向代理**:携带 Token 的请求校验后转发到 `Proxy.opened` 中放开的内部服务。
|
||||||
- **CAPTCHA 接口**:`/captcha` 生成验证码 token + 文本(内存存储,5 分钟过期,一次性使用)。
|
- **CAPTCHA 接口**:`/captcha` 生成验证码 token + 文本(内存存储,5 分钟过期,一次性使用)。
|
||||||
- **邮箱验证码**:`/register/send_code` 发送 6 位验证码邮件(60 秒有效);注册时校验,一次性消费。
|
- **邮箱验证码**:`/register/send_code` 发送 6 位验证码邮件(10 分钟有效);注册时校验,一次性消费。
|
||||||
- **速率限制**:登录 5 次/5 分钟、注册 3 次/10 分钟、发验证码 5 次/10 分钟,按 `X-Forwarded-For` 客户端 IP 计数(由 WAF 注入),超限一律返回 429。
|
- **速率限制**:登录 5 次/5 分钟、注册 3 次/10 分钟、发验证码 5 次/10 分钟,按 `X-Forwarded-For` 客户端 IP 计数(由 WAF 注入),超限一律返回 429。
|
||||||
- **OPTIONS 预检**:通配 `*` 返回 CORS 头,允许跨域。
|
- **OPTIONS 预检**:通配 `*` 返回 CORS 头,允许跨域。
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ UniServe Framework 的应用层网关,C++20 实现。
|
|||||||
|
|
||||||
### `POST /register/send_code`
|
### `POST /register/send_code`
|
||||||
|
|
||||||
向目标邮箱发送注册验证码(经 pymsg 调 smtp:8008 `send_email`,60 秒有效)。
|
向目标邮箱发送注册验证码(经 pymsg 调 smtp:8008 `send_email`,10 分钟有效)。
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "email": "user@example.com" }
|
{ "email": "user@example.com" }
|
||||||
|
|||||||
+3
-6
@@ -71,12 +71,13 @@ SMTP_USER = os.environ.get("SMTP_USER", "")
|
|||||||
SMTP_PASSWORD = os.environ.get("__PASSWORD") or os.environ.get("SMTP_PASSWORD", "")
|
SMTP_PASSWORD = os.environ.get("__PASSWORD") or os.environ.get("SMTP_PASSWORD", "")
|
||||||
|
|
||||||
CODE_LEN = 6
|
CODE_LEN = 6
|
||||||
CODE_TTL = 60 # 验证码有效期(秒)
|
CODE_TTL = 600 # 验证码有效期(秒)
|
||||||
# 多数邮箱服务商(163/QQ 等)强制 From 头与登录账号一致,故默认跟随 SMTP_USER;
|
# 多数邮箱服务商(163/QQ 等)强制 From 头与登录账号一致,故默认跟随 SMTP_USER;
|
||||||
# 仅当服务商允许自定义发件身份时才在 .env 里显式配 MAIL_FROM 覆盖
|
# 仅当服务商允许自定义发件身份时才在 .env 里显式配 MAIL_FROM 覆盖
|
||||||
MAIL_FROM = os.environ.get("MAIL_FROM") or SMTP_USER
|
MAIL_FROM = os.environ.get("MAIL_FROM") or SMTP_USER
|
||||||
DEFAULT_SUBJECT = "DNFS 邮箱验证"
|
DEFAULT_SUBJECT = "DNFS 邮箱验证"
|
||||||
DEFAULT_CONTENT = "DNFS: 您的邮箱验证码为 {code},一分钟内有效。"
|
# 有效期文案由 CODE_TTL 派生,改 TTL 不用同步改这里({{code}} 是 f-string 转义)
|
||||||
|
DEFAULT_CONTENT = f"DNFS: 您的邮箱验证码为 {{code}},{CODE_TTL // 60} 分钟内有效。"
|
||||||
|
|
||||||
code_store = {} # email -> {'code': str, 'expires_at': float}
|
code_store = {} # email -> {'code': str, 'expires_at': float}
|
||||||
STORE_LOCK = threading.Lock()
|
STORE_LOCK = threading.Lock()
|
||||||
@@ -104,10 +105,6 @@ class SmtpServer:
|
|||||||
# ── 启动 / 停止 ──────────────────────────────────────────────────
|
# ── 启动 / 停止 ──────────────────────────────────────────────────
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
"""启动服务(阻塞当前线程)。"""
|
"""启动服务(阻塞当前线程)。"""
|
||||||
# 调试:打印加载到的凭证(明文,含密码;仅 print 不落日志库,调完请删)
|
|
||||||
print(f"[smtp] 凭证加载(.env 贡献 {_env_loaded} 项): "
|
|
||||||
f"SMTP_SERVER={SMTP_SERVER!r} SMTP_PORT={SMTP_PORT} "
|
|
||||||
f"SMTP_USER={SMTP_USER!r} __PASSWORD={SMTP_PASSWORD!r}")
|
|
||||||
if not all([SMTP_SERVER, SMTP_USER, SMTP_PASSWORD]):
|
if not all([SMTP_SERVER, SMTP_USER, SMTP_PASSWORD]):
|
||||||
# 只报缺失的 key 名,绝不报值
|
# 只报缺失的 key 名,绝不报值
|
||||||
missing = [k for k, v in (("SMTP_SERVER", SMTP_SERVER),
|
missing = [k for k, v in (("SMTP_SERVER", SMTP_SERVER),
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ getCodeButton.addEventListener('click', async function () {
|
|||||||
|
|
||||||
codeTarget = email;
|
codeTarget = email;
|
||||||
codeInput.value = '';
|
codeInput.value = '';
|
||||||
codeTip.textContent = '验证码已发送至邮箱,请查收(60 秒内有效)';
|
codeTip.textContent = '验证码已发送至邮箱,请查收(10 分钟内有效)';
|
||||||
codeTip.classList.remove('tip-red', 'tip-yellow', 'tip-green');
|
codeTip.classList.remove('tip-red', 'tip-yellow', 'tip-green');
|
||||||
codeTip.classList.add('tip-green');
|
codeTip.classList.add('tip-green');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ smtp 黑盒用户模拟测试 — 发送邮箱验证码 → 校验。
|
|||||||
3. 用空参数校验 → 应报错
|
3. 用空参数校验 → 应报错
|
||||||
|
|
||||||
注意: SMTP 服务需要配置真实的邮件服务器。若服务不可达或邮件发送失败,
|
注意: SMTP 服务需要配置真实的邮件服务器。若服务不可达或邮件发送失败,
|
||||||
相关测试将标记为 SKIP。验证码有效期为 60 秒。
|
相关测试将标记为 SKIP。验证码有效期为 10 分钟(600 秒)。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
Reference in new issue
Block a user