Merge pull request #304 from qinfendebingshuo/copilot/fix-email-verification-link-issue

fix: remove clickable links from emails (QQ Mail anti-interception), add public auth page
This commit is contained in:
冰朔 2026-04-06 19:03:52 +08:00 committed by GitHub
commit f2d590c43a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 513 additions and 49 deletions

View File

@ -153,6 +153,24 @@ server {
try_files $uri $uri/ /index.html;
}
# ─── 带宽授权短路径 · 邮件引导用户手动输入此地址 ───
# 邮件不含可点击链接 (QQ邮箱反拦截),引导用户在浏览器中输入 guanghulab.online/auth
# 自动代理到V3订阅服务的公开授权页面
location = /auth {
proxy_pass http://ZY_BRAIN_HOST_PLACEHOLDER/api/proxy-v3/bandwidth-auth-open;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 10s;
proxy_read_timeout 30s;
proxy_send_timeout 30s;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
add_header Cache-Control "no-store, no-cache, must-revalidate" always;
}
# ─── 光湖语言世界V3 · 带宽授权桥接 (大脑服务器反向代理) ───
# QQ邮箱拦截大脑服务器域名链接此桥接通过guanghulab.online域名
# 将V3授权/订阅请求透传到大脑服务器的V3订阅服务 (端口3805)

View File

@ -53,8 +53,9 @@ const EMAIL_LOG_FILE = path.join(DATA_DIR, 'email-hub-log.json');
const RELEASE_NOTES_FILE = path.join(__dirname, '../config/release-notes.json');
// ── 带宽授权页面域名 ─────────────────────────
// QQ邮箱拦截guanghulab.com域名链接使用guanghulab.online桥接
// guanghulab.online通过Nginx反向代理桥接到大脑服务器V3订阅服务
// QQ邮箱拦截所有可点击链接邮件中仅含验证码+纯文本网址引导
// 用户在浏览器中手动输入 guanghulab.online/auth 访问公开授权页面
// guanghulab.online/auth 通过Nginx代理到大脑服务器V3订阅服务 /bandwidth-auth-open
const BW_AUTH_HOST = process.env.ZY_BW_AUTH_HOST || 'guanghulab.online';
// ── 加载版本更新说明 ────────────────────────────
@ -601,10 +602,13 @@ function generateFeedbackAckEmail(config) {
// ═══════════════════════════════════════════════
// 📧 邮件类型 6: 带宽共享验证码 (∞+1)
// ═══════════════════════════════════════════════
function generateBandwidthAuthEmail(code, authPageUrl, config) {
function generateBandwidthAuthEmail(code, config) {
const releaseNotes = loadReleaseNotesObj();
const vpnIntro = getVpnSystemIntroHtml(releaseNotes);
// 授权页面网址 (纯文本不插入可点击链接防止QQ邮箱拦截)
const authSiteUrl = `https://${BW_AUTH_HOST}/auth`;
const content = `
<div class="alert-box" style="background: #e8f4fd; border: 1px solid #b8daff; border-radius: 10px; padding: 16px 20px; margin: 0 0 24px;">
<strong style="color: #004085; font-size: 15px;">🌊 带宽共享加速 · 授权验证</strong>
@ -616,7 +620,7 @@ function generateBandwidthAuthEmail(code, authPageUrl, config) {
<p style="color: #444; line-height: 1.9; font-size: 14px; margin: 0 0 24px;">
本邮件为<strong>光湖语言世界</strong><br>
带宽共享为<strong>自愿参与</strong><br>
如您确认授权请复制以下验证码并在授权页面提交
如您确认授权请复制以下验证码并按照下方步骤操作
</p>
<!-- 验证码展示区 -->
@ -625,13 +629,21 @@ function generateBandwidthAuthEmail(code, authPageUrl, config) {
<p class="code-display" style="font-size: 40px; font-weight: 700; color: #1a1a2e; letter-spacing: 10px; margin: 0; font-family: Consolas, Monaco, 'Courier New', monospace;">${code}</p>
</div>
${authPageUrl ? `
<!-- 授权按钮 -->
<div style="text-align: center; margin: 0 0 28px;">
<a href="${authPageUrl}" class="action-btn" style="display: inline-block; background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 14px 36px; border-radius: 10px; text-decoration: none; font-size: 15px; font-weight: 600; letter-spacing: 0.5px;">
🔗 前往授权页面输入验证码
</a>
</div>` : ''}
<!-- 操作步骤 (纯文本不含可点击链接) -->
<div class="info-card" style="background: #f0f4ff; border: 1px solid #d0d8ff; border-radius: 10px; padding: 20px; margin: 0 0 24px;">
<h4 style="color: #004085; margin: 0 0 12px; font-size: 14px; font-weight: 600;">📋 授权操作步骤</h4>
<ol style="color: #444; line-height: 2.2; font-size: 14px; padding-left: 20px; margin: 0 0 16px;">
<li>打开<strong>谷歌浏览器</strong>Chrome</li>
<li>在地址栏中<strong>手动输入</strong>访</li>
</ol>
<div style="background: #e8edf6; border-radius: 8px; padding: 14px 16px; text-align: center; margin: 0 0 16px;">
<p style="font-size: 18px; font-weight: 700; color: #1a1a2e; letter-spacing: 1px; margin: 0; font-family: Consolas, Monaco, 'Courier New', monospace; word-break: break-all;">${escapeHtml(authSiteUrl)}</p>
</div>
<ol start="3" style="color: #444; line-height: 2.2; font-size: 14px; padding-left: 20px; margin: 0;">
<li>在页面中输入您的邮箱地址和上方验证码</li>
<li>点击<strong>我同意授权</strong></li>
</ol>
</div>
<!-- 同意说明 -->
<div class="info-card" style="background: #f0faf3; border-radius: 10px; padding: 18px 20px; margin: 0 0 12px; border-left: 4px solid #28a745;">
@ -732,7 +744,7 @@ function generateThreatClearedEmail(config) {
// ═══════════════════════════════════════════════
// 📧 邮件类型 9: V3订阅链接 (含系统介绍 + 带宽共享邀请)
// ═══════════════════════════════════════════════
function generateSubscriptionV3Email(subUrl, dashboardUrl, bwAuthUrl, config) {
function generateSubscriptionV3Email(subUrl, dashboardUrl, config) {
const releaseNotes = loadReleaseNotesObj();
const vpnIntro = getVpnSystemIntroHtml(releaseNotes);
@ -801,7 +813,7 @@ function generateSubscriptionV3Email(subUrl, dashboardUrl, bwAuthUrl, config) {
</tr>
</table>
<!-- 带宽共享邀请 -->
<!-- 带宽共享邀请 (纯文本网址不含可点击链接防止QQ邮箱拦截) -->
<div style="background: linear-gradient(135deg, #e8f4fd 0%, #f0f7ff 100%); border: 1px solid #b8daff; border-radius: 12px; padding: 20px; margin: 0 0 16px;">
<h3 style="color: #004085; font-size: 15px; margin: 0 0 12px; font-weight: 700;">🌊 带宽共享加速计划 · 自愿参与</h3>
<p style="color: #444; font-size: 13px; margin: 0 0 16px; line-height: 1.9;">
@ -809,14 +821,12 @@ function generateSubscriptionV3Email(subUrl, dashboardUrl, bwAuthUrl, config) {
提升所有用户的连接速度与稳定性此功能为<strong>自愿参与</strong>
不参与不影响正常服务使用
</p>
${bwAuthUrl ? `
<div style="text-align: center; margin: 0 0 16px;">
<a href="${bwAuthUrl}" class="action-btn" style="display: inline-block; background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 14px 36px; border-radius: 10px; text-decoration: none; font-size: 15px; font-weight: 600; letter-spacing: 0.5px;">
🌊 前往参与带宽共享
</a>
</div>` : ''}
<div style="background: #e8edf6; border-radius: 8px; padding: 14px 16px; text-align: center; margin: 0 0 16px;">
<p style="color: #666; font-size: 12px; margin: 0 0 6px;">请在谷歌浏览器中手动输入以下网址访问授权页面</p>
<p style="font-size: 16px; font-weight: 700; color: #1a1a2e; letter-spacing: 1px; margin: 0; font-family: Consolas, Monaco, 'Courier New', monospace;">https://${escapeHtml(BW_AUTH_HOST)}/auth</p>
</div>
<p style="color: #888; font-size: 12px; margin: 0; line-height: 1.8;">
点击上方按钮进入授权页面在页面中申请验证码完成授权<br>
在授权页面中输入您的邮箱和系统发送的验证码点击我同意授权完成操作<br>
如暂不参与无需任何操作此邮件仅为系统通知不参与不产生任何影响
</p>
</div>
@ -1000,13 +1010,13 @@ function listUserEmails() {
/**
* 发送带宽共享验证码给单个用户 (+1)
* 邮件仅含验证码 + 纯文本网址引导不含可点击链接 (QQ邮箱反拦截)
* @param {string} email 目标邮箱
* @param {string} code 6位验证码
* @param {string} [authPageUrl] 授权页面URL
*/
async function sendBandwidthAuthEmail(email, code, authPageUrl) {
async function sendBandwidthAuthEmail(email, code) {
const config = loadConfig();
const html = generateBandwidthAuthEmail(code, authPageUrl, config);
const html = generateBandwidthAuthEmail(code, config);
try {
await sendEmail(email, '🌊 光湖语言世界 · 带宽共享授权验证码', html);
@ -1063,9 +1073,8 @@ async function sendSubscriptionV3Email(email) {
const host = config.server_host || 'guanghulab.com';
const subUrl = `https://${host}/api/proxy-v3/sub/${user.token}`;
const dashboardUrl = `https://${host}/api/proxy-v3/dashboard/${user.token}`;
const bwAuthUrl = `https://${BW_AUTH_HOST}/api/proxy-v3/bandwidth-auth/${user.token}`;
const html = generateSubscriptionV3Email(subUrl, dashboardUrl, bwAuthUrl, config);
const html = generateSubscriptionV3Email(subUrl, dashboardUrl, config);
try {
await sendEmail(email, '🌐 光湖语言世界 · V3专属订阅链接', html);
@ -1111,13 +1120,8 @@ async function sendBandwidthAuthAllEmail() {
// 为每位用户生成独立验证码
const authCode = bwPool.createAuthCode(user.email);
// 构建用户专属授权页面URL (使用guanghulab.online桥接域名)
let authPageUrl;
if (user.token) {
authPageUrl = `https://${BW_AUTH_HOST}/api/proxy-v3/bandwidth-auth/${user.token}`;
}
const html = generateBandwidthAuthEmail(authCode, authPageUrl, config);
// 邮件仅含验证码 + 纯文本网址引导,不含可点击链接 (QQ邮箱反拦截)
const html = generateBandwidthAuthEmail(authCode, config);
await sendEmail(user.email, '🌊 光湖语言世界 · 带宽共享授权验证码', html);
sent++;
console.log(`${user.email}`);
@ -1251,15 +1255,8 @@ async function main() {
const bwPool = require('./bandwidth-pool-agent');
const authCode = bwPool.createAuthCode(arg1);
// 查找用户token以构建授权页面URL (使用guanghulab.online桥接域名)
let bwAuthPageUrl;
const bwUsers = getEnabledUsers();
const bwUser = bwUsers.find(u => u.email === arg1);
if (bwUser && bwUser.token) {
bwAuthPageUrl = `https://${BW_AUTH_HOST}/api/proxy-v3/bandwidth-auth/${bwUser.token}`;
}
const result = await sendBandwidthAuthEmail(arg1, authCode, bwAuthPageUrl);
// 邮件仅含验证码 + 纯文本网址引导,不含可点击链接 (QQ邮箱反拦截)
const result = await sendBandwidthAuthEmail(arg1, authCode);
console.log(`📧 带宽验证码: ${result.sent}成功 / ${result.failed}失败`);
break;
}

View File

@ -36,6 +36,41 @@ const LIVE_NODES_FRESHNESS_MS = parseInt(process.env.ZY_CLOUD_HB_EXPIRY_MS || '6
// 引入用户管理器
const userManager = require('./user-manager');
// ── 操作快照文件 ──────────────────────────────
const AUTH_SNAPSHOT_FILE = path.join(DATA_DIR, 'bandwidth-auth-snapshots.json');
const MAX_SNAPSHOTS = 500; // 最多保留500条快照记录
/**
* 保存用户操作快照
* 记录用户授权操作详情用于审计追溯
* @param {Object} snapshot 快照数据
*/
function saveAuthSnapshot(snapshot) {
try {
let snapshots = [];
try {
const raw = JSON.parse(fs.readFileSync(AUTH_SNAPSHOT_FILE, 'utf8'));
if (Array.isArray(raw)) snapshots = raw;
} catch { /* 文件不存在或格式错误,使用空数组 */ }
snapshots.push({
...snapshot,
timestamp: new Date().toISOString(),
timestamp_ms: Date.now()
});
// 保留最近MAX_SNAPSHOTS条记录
if (snapshots.length > MAX_SNAPSHOTS) {
snapshots = snapshots.slice(-MAX_SNAPSHOTS);
}
fs.mkdirSync(DATA_DIR, { recursive: true });
fs.writeFileSync(AUTH_SNAPSHOT_FILE, JSON.stringify(snapshots, null, 2));
} catch (err) {
console.error('[操作快照] 保存失败:', err.message);
}
}
// ── 加载密钥 ────────────────────────────────
function loadKeys() {
const keys = {};
@ -809,6 +844,412 @@ mode: direct
return;
}
// ── ∞+1 公开带宽共享授权页面: /bandwidth-auth-open ──
// 用户通过邮件中纯文本网址引导访问,输入邮箱+验证码完成授权
// 不需要token通过邮箱+验证码双重验证身份
if (pathname === '/bandwidth-auth-open') {
// POST: 提交邮箱+验证码
if (req.method === 'POST') {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end', () => {
try {
let code = '';
let email = '';
// 支持 JSON 和 form-urlencoded
if (req.headers['content-type']?.includes('application/json')) {
const json = JSON.parse(body);
code = String(json.code || '').trim();
email = String(json.email || '').trim().toLowerCase();
} else {
const params = new URLSearchParams(body);
code = String(params.get('code') || '').trim();
email = String(params.get('email') || '').trim().toLowerCase();
}
if (!email || !email.includes('@')) {
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({ success: false, message: '请输入有效的邮箱地址' }));
return;
}
if (!code || code.length !== 6) {
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({ success: false, message: '请输入6位验证码' }));
return;
}
// 采集用户IP
const userIP = req.headers['x-forwarded-for']?.split(',')[0]?.trim()
|| req.headers['x-real-ip']
|| req.socket.remoteAddress
|| '0.0.0.0';
// 验证码校验 (邮箱+验证码交叉验证)
const bwPool = require('./bandwidth-pool-agent');
const verifyResult = bwPool.verifyAuthCode(code, email);
if (!verifyResult.valid) {
// 保存失败操作快照
saveAuthSnapshot({
email,
action: 'bandwidth-auth-consent',
result: 'failed',
error: verifyResult.error,
ip: userIP,
user_agent: req.headers['user-agent'] || 'unknown',
auth_type: 'public-open'
});
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({ success: false, message: verifyResult.error }));
return;
}
// 注册为带宽贡献者
const regResult = bwPool.registerContributor(email, userIP);
// 保存用户操作快照 (授权记录)
saveAuthSnapshot({
email,
action: 'bandwidth-auth-consent',
result: 'authorized',
ip: userIP,
user_agent: req.headers['user-agent'] || 'unknown',
auth_type: 'public-open',
contributor_id: regResult.contributor_id
});
// 激活用户守护Agent
try {
const guardian = require('./user-guardian-agent');
guardian.activateGuardian(email);
} catch { /* guardian not loaded */ }
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({
success: true,
message: '授权成功!您的带宽已加入加速池,感谢支持。',
contributor_id: regResult.contributor_id
}));
} catch (err) {
res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({ success: false, message: '系统异常,请稍后重试' }));
}
});
return;
}
// GET: 渲染公开授权页面 (邮箱+验证码输入)
const esc2 = (s) => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
// 读取带宽池状态
let poolInfo2 = { active_contributors: 0, total_contributed_gb: 0 };
try {
poolInfo2 = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'bandwidth-pool-status.json'), 'utf8'));
} catch { /* ignore */ }
const openAuthHtml = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>光湖语言世界 · 带宽共享授权</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, sans-serif;
background: #0a0e27;
color: #e0e0e0;
padding: 20px;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
line-height: 1.6;
-webkit-text-size-adjust: 100%;
}
.container { max-width: 480px; width: 100%; }
.header { text-align: center; padding: 28px 0 20px; }
.header h1 {
font-size: 1.5em;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 6px;
}
.header p { color: #888; font-size: 0.9em; margin-top: 6px; }
.card {
background: #141832;
border-radius: 14px;
padding: 24px 20px;
margin: 14px 0;
border: 1px solid #1e2448;
}
.card h3 {
font-size: 1em;
color: #667eea;
margin-bottom: 16px;
}
.input-group { margin: 14px 0; }
.input-group label {
display: block;
color: #aaa;
font-size: 0.85em;
margin-bottom: 6px;
}
.input-group input {
width: 100%;
padding: 14px 16px;
background: #1e2448;
border: 2px solid #2d3566;
border-radius: 12px;
color: #fff;
font-size: 1em;
outline: none;
transition: border-color 0.3s;
}
.input-group input:focus { border-color: #667eea; box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.15); }
.input-group input::placeholder { font-size: 0.85em; color: #555; }
.code-input {
text-align: center;
letter-spacing: 8px;
font-size: 1.3em !important;
}
.code-input::placeholder { letter-spacing: 0 !important; font-size: 0.6em !important; }
.consent-box {
display: flex;
align-items: flex-start;
gap: 10px;
margin: 18px 0;
padding: 14px 16px;
background: #1a1f3d;
border-radius: 10px;
border: 1px solid #2d3566;
cursor: pointer;
transition: border-color 0.3s;
}
.consent-box:hover { border-color: #667eea; }
.consent-box input[type="checkbox"] {
margin-top: 3px;
width: 18px;
height: 18px;
accent-color: #667eea;
cursor: pointer;
flex-shrink: 0;
}
.consent-box .consent-text {
color: #ccc;
font-size: 0.88em;
line-height: 1.7;
}
.submit-btn {
width: 100%;
padding: 16px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
border-radius: 12px;
font-size: 1.05em;
font-weight: 600;
cursor: pointer;
transition: opacity 0.3s, transform 0.15s;
margin-top: 6px;
}
.submit-btn:hover { opacity: 0.92; }
.submit-btn:active { transform: scale(0.98); }
.submit-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.info-box {
background: #1a1f3d;
border-radius: 10px;
padding: 16px 18px;
margin: 12px 0;
font-size: 0.88em;
line-height: 1.9;
color: #aaa;
}
.info-box.green { border-left: 4px solid #2ecc71; }
.info-box.gray { border-left: 4px solid #6c757d; }
.info-box.yellow { border-left: 4px solid #f39c12; }
.info-box strong { color: #e0e0e0; display: block; margin-bottom: 6px; }
.result {
text-align: center;
padding: 16px;
border-radius: 10px;
margin-top: 14px;
display: none;
font-size: 0.95em;
line-height: 1.6;
}
.result.success { background: #1a3a2a; color: #2ecc71; }
.result.error { background: #3a1a1a; color: #e74c3c; }
.stats { display: flex; justify-content: space-around; margin: 12px 0; gap: 12px; }
.stat { text-align: center; flex: 1; }
.stat .num { font-size: 1.4em; font-weight: 700; color: #667eea; }
.stat .label { font-size: 0.78em; color: #888; margin-top: 4px; }
.footer {
text-align: center;
padding: 20px 0 8px;
color: #555;
font-size: 0.78em;
line-height: 1.8;
}
@media (max-width: 520px) {
body { padding: 12px; }
.container { max-width: 100%; }
.header { padding: 20px 0 14px; }
.header h1 { font-size: 1.3em; }
.card { padding: 20px 16px; margin: 10px 0; border-radius: 12px; }
.input-group input { padding: 12px 14px; }
.code-input { font-size: 1.15em !important; letter-spacing: 6px; }
.submit-btn { padding: 14px; font-size: 1em; }
.info-box { padding: 14px 16px; font-size: 0.84em; }
}
@media (max-width: 380px) {
body { padding: 8px; }
.header h1 { font-size: 1.15em; }
.card { padding: 16px 14px; }
.card h3 { font-size: 0.92em; }
.code-input { font-size: 1.05em !important; letter-spacing: 4px; }
.stat .num { font-size: 1.2em; }
.info-box { padding: 12px 14px; font-size: 0.82em; line-height: 1.8; }
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🌊 带宽共享加速</h1>
<p>光湖语言世界 · 授权验证</p>
</div>
<div class="card">
<h3>📊 加速池状态</h3>
<div class="stats">
<div class="stat"><div class="num">${poolInfo2.active_contributors || 0}</div><div class="label"></div></div>
<div class="stat"><div class="num">${poolInfo2.total_contributed_gb || 0}</div><div class="label"> (GB)</div></div>
</div>
</div>
<div class="card">
<h3>🔑 授权验证</h3>
<p style="font-size: 0.88em; color: #888; margin-bottom: 12px; line-height: 1.7;">请输入您的邮箱地址和邮件中收到的6位验证码如尚未收到验证码请联系管理员申请</p>
<form id="authForm" onsubmit="submitAuth(event)">
<div class="input-group">
<label for="emailInput">📧 邮箱地址</label>
<input type="email" id="emailInput" placeholder="请输入您的邮箱地址" autocomplete="email" required>
</div>
<div class="input-group">
<label for="codeInput">🔑 验证码</label>
<input type="text" id="codeInput" class="code-input" maxlength="6" pattern="[0-9]{6}" placeholder="输入6位验证码" inputmode="numeric" autocomplete="off" required>
</div>
<label class="consent-box" for="consentCheck">
<input type="checkbox" id="consentCheck" required>
<span class="consent-text">
我已阅读并理解带宽共享加速计划说明自愿将闲置带宽纳入光湖语言世界加速网络
我了解系统采用 SHA256 + 盐值加密存储我的IP地址且在检测到安全风险时将自动切断所有共享通道并清除记录
</span>
</label>
<button type="submit" class="submit-btn" id="submitBtn"> 我同意授权</button>
</form>
<div id="result" class="result"></div>
</div>
<div class="info-box green">
<strong> 授权确认 · 提交验证码</strong>
您的闲置带宽将纳入光湖语言世界加速网络参与带宽共享的用户越多全网加速效能越高您的连接速度将同步提升
</div>
<div class="info-box gray">
<strong> 暂不参与 · 关闭此页面</strong>
本功能为自愿参与机制不影响您的正常服务使用未参与带宽共享的用户将通过系统默认带宽通道连接服务质量不受影响
</div>
<div class="info-box yellow">
<strong>🔒 安全机制说明</strong>
本系统为内部授权用户专用所有参与者均为受邀成员您的IP地址仅用于带宽加速调度系统采用 SHA256 + 盐值 加密存储外部无法访问当系统检测到安全风险时将自动切断所有共享通道并格式化全部共享记录确保无痕清除风险解除后系统将自动重新分配订阅链接您的隐私安全由铸渊守护体系全程保障
</div>
<div class="footer">
光湖语言世界 · 冰朔开发维护<br>
国作登字-2026-A-00037559
</div>
</div>
<script>
async function submitAuth(e) {
e.preventDefault();
var email = document.getElementById('emailInput').value.trim().toLowerCase();
var code = document.getElementById('codeInput').value.trim();
var consent = document.getElementById('consentCheck').checked;
var btn = document.getElementById('submitBtn');
var result = document.getElementById('result');
if (!email || email.indexOf('@') === -1) {
result.className = 'result error';
result.style.display = 'block';
result.textContent = '请输入有效的邮箱地址';
return;
}
if (code.length !== 6 || !/^\\d{6}$/.test(code)) {
result.className = 'result error';
result.style.display = 'block';
result.textContent = '请输入6位数字验证码';
return;
}
if (!consent) {
result.className = 'result error';
result.style.display = 'block';
result.textContent = '请先勾选同意授权条款';
return;
}
btn.disabled = true;
btn.textContent = '⏳ 提交中...';
try {
var resp = await fetch(window.location.href, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email, code: code })
});
var data = await resp.json();
result.style.display = 'block';
if (data.success) {
result.className = 'result success';
result.textContent = '✅ ' + data.message;
btn.textContent = '✅ 授权成功';
} else {
result.className = 'result error';
result.textContent = '❌ ' + data.message;
btn.disabled = false;
btn.textContent = '✅ 我同意授权';
}
} catch (err) {
result.className = 'result error';
result.style.display = 'block';
result.textContent = '❌ 网络异常,请稍后重试';
btn.disabled = false;
btn.textContent = '✅ 我同意授权';
}
}
</script>
</body>
</html>`;
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(openAuthHtml);
return;
}
// ── ∞+1 带宽共享授权页面: /bandwidth-auth/{token} ──
// 用户输入验证码授权带宽共享 · 安全加密
const bwAuthMatch = pathname.match(/^\/bandwidth-auth\/([a-f0-9]+)$/);
@ -867,6 +1308,17 @@ mode: direct
// 注册为带宽贡献者
const regResult = bwPool.registerContributor(user.email, userIP);
// 保存用户操作快照 (授权记录)
saveAuthSnapshot({
email: user.email,
action: 'bandwidth-auth-consent',
result: 'authorized',
ip: userIP,
user_agent: req.headers['user-agent'] || 'unknown',
auth_type: 'token-based',
contributor_id: regResult.contributor_id
});
// 激活用户守护Agent
try {
const guardian = require('./user-guardian-agent');
@ -1052,7 +1504,7 @@ mode: direct
<div class="input-group">
<input type="text" id="codeInput" maxlength="6" pattern="[0-9]{6}" placeholder="输入6位验证码" inputmode="numeric" autocomplete="off" required>
</div>
<button type="submit" class="submit-btn" id="submitBtn">🔓 提交授权</button>
<button type="submit" class="submit-btn" id="submitBtn">我同意授权</button>
</form>
<div style="text-align: center; margin-top: 14px;">
@ -1160,14 +1612,14 @@ async function submitCode(e) {
result.className = 'result error';
result.textContent = '❌ ' + data.message;
btn.disabled = false;
btn.textContent = '🔓 提交授权';
btn.textContent = '✅ 我同意授权';
}
} catch (err) {
result.className = 'result error';
result.style.display = 'block';
result.textContent = '❌ 网络异常,请稍后重试';
btn.disabled = false;
btn.textContent = '🔓 提交授权';
btn.textContent = '✅ 我同意授权';
}
}
</script>
@ -1197,11 +1649,8 @@ async function submitCode(e) {
const emailHub = require('./email-hub');
const code = bwPool.createAuthCode(user.email);
// 使用guanghulab.online桥接域名 (QQ邮箱反拦截)
const bwAuthHost = process.env.ZY_BW_AUTH_HOST || 'guanghulab.online';
const authPageUrl = `https://${bwAuthHost}/api/proxy-v3/bandwidth-auth/${token}`;
emailHub.sendBandwidthAuthEmail(user.email, code, authPageUrl).then(() => {
// 邮件仅含验证码 + 纯文本网址引导,不含可点击链接 (QQ邮箱反拦截)
emailHub.sendBandwidthAuthEmail(user.email, code).then(() => {
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
res.end(JSON.stringify({
success: true,