Files
ameiba_cn_new/cms/server/src/middleware/auth.js
T

37 lines
1.5 KiB
JavaScript

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: '登录失效' });
}
}