import jwt from 'jsonwebtoken'; import crypto from 'crypto'; import 'dotenv/config'; const SECRET = process.env.JWT_SECRET || (process.env.NODE_ENV === 'production' ? (() => { throw new Error('JWT_SECRET must be configured in production'); })() : crypto.randomBytes(32).toString('hex')); export function signToken(payload) { return jwt.sign(payload, SECRET, { expiresIn: '12h' }); } export function verifyToken(token) { return jwt.verify(token, SECRET); } export function authMiddleware(req, res, next) { // 静态资源与诊断公开 if (req.path.startsWith('/admin') || req.path.startsWith('/uploads') || req.path === '/health' || req.path === '/') return next(); // 诊断相关全部公开(问卷、会话、报告、留资、分享、PDF)- 但CMS诊断后台需鉴权 if (req.path.startsWith('/api/diagnosis/')) return next(); // 所有 CMS 管理接口(包括 GET)都必须鉴权;只有下方聚合公开接口例外。 if (req.path === '/api/auth/login' || req.path === '/api/cms/public' || req.path === '/api/contact/leads') return next(); // 上传也需鉴权 const auth = req.headers.authorization; if (!auth || !auth.startsWith('Bearer ')) { if (req.path === '/api/cms/public' || req.path === '/api/contact/leads') return next(); return res.status(401).json({ code: 401, msg: '未登录' }); } try { const token = auth.slice(7); const decoded = jwt.verify(token, SECRET); req.user = decoded; next(); } catch (e) { return res.status(401).json({ code: 401, msg: '登录失效' }); } }