/** * 管理员认证中间件 * Session/Cookie 保护 /dashboard 和 /api/stats */ import cookieParser from 'cookie-parser'; // Session 存储(生产环境应使用 Redis) const SESSIONS: Map = new Map(); // Session 有效期 24 小时 const SESSION_EXPIRY = 24 * 60 * 60 * 1000; // 环境变量凭证 const ADMIN_USER = process.env.ADMIN_USER || 'admin'; const ADMIN_PASS = process.env.ADMIN_PASS || ''; // Session Secret(用于签名) const SESSION_SECRET = process.env.SESSION_SECRET || 'default-secret-change-me'; /** * 初始化 Cookie Parser */ export function initCookieParser() { return cookieParser(); } /** * 生成 Session Token */ function generateSessionToken(): string { const randomBytes = new Uint8Array(32); crypto.getRandomValues(randomBytes); return Array.from(randomBytes).map(b => b.toString(16).padStart(2, '0')).join(''); } /** * 验证凭证并创建 Session */ export function createSession(user: string, pass: string): { success: boolean; token?: string; error?: string } { // 检查凭证 if (user !== ADMIN_USER || pass !== ADMIN_PASS) { return { success: false, error: 'Invalid credentials' }; } // 检查是否配置了密码 if (!ADMIN_PASS) { return { success: false, error: 'Admin password not configured' }; } // 创建 Session const token = generateSessionToken(); const expires = Date.now() + SESSION_EXPIRY; SESSIONS.set(token, { user, expires }); console.log('[Auth] Session created for user:', user); return { success: true, token }; } /** * 验证 Session Token */ export function validateSession(token: string): { valid: boolean; user?: string } { const session = SESSIONS.get(token); if (!session) { return { valid: false }; } if (session.expires < Date.now()) { SESSIONS.delete(token); return { valid: false }; } return { valid: true, user: session.user }; } /** * 删除 Session(注销) */ export function destroySession(token: string): void { SESSIONS.delete(token); console.log('[Auth] Session destroyed'); } /** * 路由保护中间件 * 检查 Session Cookie,未登录重定向到 /login */ export function requireAdmin(req: any, res: any, next: any): void { const session = req.cookies?.admin_session; if (!session) { return res.redirect('/login'); } const validation = validateSession(session); if (!validation.valid) { return res.redirect('/login'); } // 设置用户信息到请求对象 req.user = validation.user; next(); } /** * API 保护中间件 * 检查 Session,返回 401 JSON 响应 */ export function requireAdminApi(req: any, res: any, next: any): void { const session = req.cookies?.admin_session; if (!session) { return res.status(401).json({ error: 'Unauthorized' }); } const validation = validateSession(session); if (!validation.valid) { return res.status(401).json({ error: 'Session expired' }); } req.user = validation.user; next(); } /** * 清理过期 Session(可定期调用) */ export function cleanupExpiredSessions(): number { const now = Date.now(); let cleaned = 0; for (const [token, session] of SESSIONS.entries()) { if (session.expires < now) { SESSIONS.delete(token); cleaned++; } } if (cleaned > 0) { console.log('[Auth] Cleaned', cleaned, 'expired sessions'); } return cleaned; }