* feat: add Turnstile CAPTCHA for login forms (#767) Add optional Turnstile verification for admin login, user login, and address password login via ENABLE_LOGIN_TURNSTILE_CHECK env var. Does not affect existing Turnstile on address creation / registration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add ENABLE_LOGIN_TURNSTILE_CHECK to wrangler.toml.template Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: ensure openSettings loaded before admin login modal Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Turnstile to site access password and fix settings field name - Add Turnstile to site access password modal in Header.vue - Add /open_api/site_login endpoint for password + Turnstile verification - Fix settings field name from enableTurnstileLogin to enableLoginTurnstileCheck Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: move login endpoints to open_api/auth.ts Move /open_api/site_login and /open_api/admin_login from commom_api.ts to a dedicated open_api/auth.ts file for better code organization. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: change Turnstile check failure status from 500 to 400 Turnstile validation failure is a client error, not a server error. Change all Turnstile check error responses from 500 to 400. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: use unique IDs for multiple Turnstile instances When multiple modals with Turnstile appear simultaneously (e.g., site access + admin login), the hardcoded id="cf-turnstile" causes conflicts. Generate a unique container ID per Turnstile instance to fix this. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: review fixes - cfToken separation, register Turnstile, error codes - Separate cfToken refs in Login.vue to avoid token sharing between login and new address creation Turnstile instances - Add Turnstile check to user registration endpoint (not just verify_code) - Show Turnstile on register tab regardless of enableMailVerify - Pass cf_token in register request body - Fix site_login error message to use CustomAuthPasswordMsg - Fix verifyCode Turnstile error status from 500 to 400 - Restore empty line in commom_api.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: separate register Turnstile logic for with/without mail verify - With mail verify: verify_code already checks Turnstile, register skips Turnstile (token is one-time use) - Without mail verify: register checks Turnstile directly - Separate loginCfToken for login tab to avoid token sharing with register tab Turnstile Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add enableLoginTurnstileCheck to store defaults, simplify changelog Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add /open_api/credential_login for credential login verification Add credential_login endpoint that verifies both Turnstile token and JWT credential server-side, replacing the generic verify_turnstile endpoint. Credential login now validates the JWT before accepting it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: improve login endpoints - hash passwords, expose Turnstile refresh, fix status codes - site_login/admin_login: always called, verify hashed password + optional Turnstile - credential_login: always called, verify JWT + optional Turnstile - Frontend sends hashed passwords instead of plaintext - Turnstile component exposes refresh method via defineExpose - Fix Turnstile error status 500→400 in mails_api and telegram_api Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: rename to ENABLE_GLOBAL_TURNSTILE_CHECK and add isGlobalTurnstileEnabled helper - Rename ENABLE_LOGIN_TURNSTILE_CHECK -> ENABLE_GLOBAL_TURNSTILE_CHECK - Add isGlobalTurnstileEnabled() in utils.ts: checks env var + Turnstile keys all present - Backend settings returns enableGlobalTurnstileCheck computed from the helper - All backend endpoints use isGlobalTurnstileEnabled(c) instead of raw env check - Update all frontend refs, docs, changelog, and wrangler template Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: use utils.isGlobalTurnstileEnabled instead of named import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add E2E tests for turnstile login endpoints - Test all 3 new /open_api/* endpoints when ENABLE_GLOBAL_TURNSTILE_CHECK is disabled - Verify settings returns enableGlobalTurnstileCheck: false - Test admin_login with correct/wrong/empty hashed password - Test site_login returns 401 when no PASSWORDS configured - Test credential_login with valid JWT, invalid JWT, empty credential - Test address_login with empty cf_token works when turnstile disabled - Add ADMIN_PASSWORDS to E2E wrangler config for admin_login tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: rename test file to login-endpoints.spec.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: validate JWT payload has address field in credential_login Prevents user tokens or challenge tokens from being accepted as address credentials since they share the same JWT_SECRET. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: refresh Turnstile token on login failure to allow retry After a failed login attempt, the consumed Turnstile token is now refreshed so users can retry without manually refreshing. Also adds ref to signup Turnstile in UserLogin.vue to refresh after verification code is sent (single-use token consumed). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: separate Turnstile tokens for signup and reset password flows Split shared cfToken into signupCfToken and resetCfToken to prevent single-use Turnstile token conflicts between signup tab and reset password modal. Each flow now has its own token ref and refreshes the correct Turnstile widget after use. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update comments from "login turnstile" to "global turnstile" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
15 KiB
Worker 变量说明
[!NOTE] 注意 通过 CLI 部署时的写法请参考
worker/wrangler.toml.template
必填变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
DOMAINS |
JSON | 用于临时邮箱的所有域名, 支持多个域名 | ["awsl.uk", "dreamhunter2333.xyz"] |
JWT_SECRET |
文本/Secret | 用于生成 jwt 的密钥, jwt 用于登录以及鉴权 | xxx |
ADMIN_PASSWORDS |
JSON | admin 控制台密码, 不配置则不允许访问控制台 | ["123", "456"] |
ENABLE_USER_CREATE_EMAIL |
文本/JSON | 是否允许用户创建邮箱, 不配置则不允许 | true |
ENABLE_USER_DELETE_EMAIL |
文本/JSON | 是否允许用户删除邮件, 不配置则不允许 | true |
后台相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
PASSWORDS |
JSON | 网站私有密码, 配置后需要密码才能访问 | ["123", "456"] |
DISABLE_ADMIN_PASSWORD_CHECK |
文本/JSON | 警告: 管理员控制台没有密码或用户检查 | false |
邮箱相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
PREFIX |
文本 | 新建 邮箱名称 的默认前缀,不需要前缀可不配置 |
tmp |
MIN_ADDRESS_LEN |
数字 | 邮箱名称 的最小长度 |
1 |
MAX_ADDRESS_LEN |
数字 | 邮箱名称 的最大长度 |
30 |
DISABLE_CUSTOM_ADDRESS_NAME |
文本/JSON | 禁用自定义邮箱地址名称,如果设置为 true,则用户无法输入自定义邮箱名称,将由后台自动生成 | true |
ADDRESS_CHECK_REGEX |
文本 | 邮箱名称 的正则表达式, 只用于检查 |
^(?!.*admin).* |
ADDRESS_REGEX |
文本 | 邮箱名称 替换非法符号的正则表达式, 不在其中的符号将被替换,如果不设置,默认为 [^a-z0-9], 需谨慎使用, 有些符号可能导致无法收件 |
[^a-z0-9] |
DEFAULT_DOMAINS |
JSON | 默认用户可用的域名(未登录或未分配角色的用户) | ["awsl.uk", "dreamhunter2333.xyz"] |
CREATE_ADDRESS_DEFAULT_DOMAIN_FIRST |
文本/JSON | 创建新地址时是否优先使用默认域名,如果设置为 true,当未指定域名时将使用第一个域名, 主要用于 telegram bot 场景 | false |
DOMAIN_LABELS |
JSON | 对于中文域名,可以使用 DOMAIN_LABELS 显示域名的中文展示名称 | ["中文.awsl.uk", "dreamhunter2333.xyz"] |
ENABLE_AUTO_REPLY |
文本/JSON | 允许自动回复邮件。发件人过滤(source_prefix)支持三种模式:留空匹配所有发件人、填写前缀进行 startsWith 匹配、使用 /regex/ 语法进行正则匹配(如 /@example\.com$/) |
true |
DEFAULT_SEND_BALANCE |
文本/JSON | 默认发送邮件余额,如果不设置,将为 0 | 1 |
ENABLE_ADDRESS_PASSWORD |
文本/JSON | 启用邮箱地址密码功能,启用后创建新地址时会自动生成密码,并支持密码登录和修改 | true |
接受邮件相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
BLACK_LIST |
文本 | 黑名单,用于过滤发件人,逗号分隔 | gov.cn,edu.cn |
ENABLE_CHECK_JUNK_MAIL |
文本/JSON | 是否启用垃圾邮件检查,配合下列两个列表使用 | false |
JUNK_MAIL_CHECK_LIST |
JSON | 垃圾邮件检查配置, 任何一项 存在 且 不通过 则被判定为垃圾邮件 |
["spf", "dkim", "dmarc"] |
JUNK_MAIL_FORCE_PASS_LIST |
JSON | 垃圾邮件检查配置, 任何一项 不存在 或者 不通过 则被判定为垃圾邮件 |
["spf", "dkim", "dmarc"] |
FORWARD_ADDRESS_LIST |
JSON | 全局转发地址列表,如果不配置则不启用,启用后所有邮件都会转发到列表中的地址 | ["xxx@xxx.com"] |
REMOVE_EXCEED_SIZE_ATTACHMENT |
文本/JSON | 如果附件大小超过 2MB,则删除附件,邮件可能由于解析而丢失一些信息 | true |
REMOVE_ALL_ATTACHMENT |
文本/JSON | 移除所有附件,邮件可能由于解析而丢失一些信息 | true |
Note
垃圾邮件检查和移除附件功能需要解析邮件,免费版 CPU 有限,可能会导致大邮件解析超时如果你想解析邮件能力更强
webhook 相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
ENABLE_WEBHOOK |
文本/JSON | 是否启用 webhook | true |
FRONTEND_URL |
文本 | 前端地址,用于发送 webhook 的邮件 url | https://xxxx.xxx |
Note
webhook 功能需要解析邮件,免费版 CPU 有限,可能会导致大邮件解析超时
如果你想解析邮件能力更强
用户相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
USER_DEFAULT_ROLE |
文本 | 新用户默认角色, 仅在启用邮件验证时有效 | vip |
ADMIN_USER_ROLE |
文本 | admin 角色配置, 如果用户角色等于 ADMIN_USER_ROLE 则可以访问 admin 控制台 | admin |
USER_ROLES |
JSON | - | 见下方 |
DISABLE_ANONYMOUS_USER_CREATE_EMAIL |
文本/JSON | 禁用匿名用户创建邮箱,如果设置为 true,则用户只能在登录后创建邮箱地址 | true |
NO_LIMIT_SEND_ROLE |
文本 | 可以无限发送邮件的角色, 多个角色使用逗号分割 vip,admin |
vip |
[!NOTE] USER_ROLES 用户角色配置说明
- 如果
domains为空将使用DEFAULT_DOMAINS- 如果 prefix 为 null 将使用默认前缀, 如果 prefix 为空字符串将不使用前缀
通过用户界面部署时
USER_ROLES请配置为此格式[{"domains":["awsl.uk","dreamhunter2333.xyz"],"role":"vip","prefix":"vip"},{"domains":["awsl.uk","dreamhunter2333.xyz"],"role":"admin","prefix":""}]CLI 部署时
USER_ROLES请参考worker/wrangler.toml.template配置为此格式[{ domains = ["awsl.uk", "dreamhunter2333.xyz"], role = "vip", prefix = "vip" }, { domains = ["awsl.uk", "dreamhunter2333.xyz"], role = "admin", prefix = "" }]
网页相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
DEFAULT_LANG |
文本 | Worker 错误信息默认语言, zh/en | zh |
TITLE |
文本 | 自定义前端页面网站标题,支持 html | Custom Title |
ANNOUNCEMENT |
文本 | 自定义前端页面公告,支持 html | Custom Announcement |
ALWAYS_SHOW_ANNOUNCEMENT |
文本/JSON | 是否总是显示公告(即使无更改), 默认 false |
true |
COPYRIGHT |
文本 | 自定义前端界面页脚文本,支持 html | Dream Hunter |
ADMIN_CONTACT |
文本 | admin 联系方式,可配置任意字符串, 不配置则不显示 | xxx@gmail.com |
DISABLE_SHOW_GITHUB |
文本/JSON | 是否显示 GitHub 链接 | true |
STATUS_URL |
文本 | 状态监控页面 URL,配置后显示 Status 菜单按钮 | https://status.example.com |
CF_TURNSTILE_SITE_KEY |
文本/Secret | Turnstile 人机验证配置(用于新建邮箱、注册验证码等) | xxx |
CF_TURNSTILE_SECRET_KEY |
文本/Secret | Turnstile 人机验证配置(用于新建邮箱、注册验证码等) | xxx |
ENABLE_GLOBAL_TURNSTILE_CHECK |
文本/JSON | 启用全局登录表单的 Turnstile 人机验证(管理员登录、用户登录、邮箱密码登录),需同时配置上述 Turnstile 密钥 | true |
Telegram Bot 相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
TG_MAX_ADDRESS |
数字 | telegram bot 最多绑定邮箱数量 | 5 |
TG_BOT_INFO |
文本 | 可不配置,telegram BOT_INFO,预定义的 BOT_INFO 可以降低 webhook 的延迟 | {} |
TG_ALLOW_USER_LANG |
文本/JSON | 是否允许用户通过 /lang 命令切换语言,默认 false |
true |
Note
Telegram 功能需要解析邮件,免费版 CPU 有限,可能会导致大邮件解析超时
如果你想解析邮件能力更强
邮件转发相关变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
SUBDOMAIN_FORWARD_ADDRESS_LIST |
JSON | 子域名/规则转发配置,支持按域名和来源地址正则过滤转发 | 见下方 |
[!NOTE] SUBDOMAIN_FORWARD_ADDRESS_LIST 配置说明
v1.2.0 新增
sourcePatterns和sourceMatchMode字段,支持按发件人地址正则过滤转发:
domains: 目标域名列表,为空则匹配所有域名forward: 转发目标地址sourcePatterns: 来源地址正则表达式列表(可选)sourceMatchMode: 匹配模式,any(任一匹配,默认) 或all(全部匹配)正则表达式最大长度 200 字符,防止 ReDoS 攻击
SUBDOMAIN_FORWARD_ADDRESS_LIST = """ [ {"domains":[""],"forward":"xxx1@xxx.com"}, {"domains":["subdomain-1.domain.com","subdomain-2.domain.com"],"forward":"xxx2@xxx.com"}, {"domains":["example.com"],"forward":"admin@xxx.com","sourcePatterns":[".*@github.com",".*@gitlab.com"],"sourceMatchMode":"any"} ] """
其他变量
| 变量名 | 类型 | 说明 | 示例 |
|---|---|---|---|
ENABLE_ANOTHER_WORKER |
文本/JSON | 是否开启其他 worker 处理邮件 | false |
ANOTHER_WORKER_LIST |
JSON | - 其他 worker 处理邮件的配置,可以配置多个其他 worker - 通过关键词筛选,调用对应绑定的 worker 的方法(默认方法名为 rpcEmail) - keywords必填,否则 worker 将不会被触发 |
见下方 |
Note
ANOTHER_WORKER_LIST的配置示例#ANOTHER_WORKER_LIST =""" #[ # { # "binding":"AUTH_INBOX", # "method":"rpcEmail", # "keywords":[ # "验证码","激活码","激活链接","确认链接","验证邮箱","确认邮件","账号激活","邮件验证","账户确认","安全码","认证码","安全验证","登陆码","确认码","启用账户","激活账户","账号验证","注册确认", # "account","activation","verify","verification","activate","confirmation","email","code","validate","registration","login","code","expire","confirm" # ] # } #] #