Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import { Context, Next } from 'koa'; import jwt from 'jsonwebtoken'; import { config } from '../config'; import { UnauthorizedError, AppError } from './errorHandler'; import { JwtPayload } from '../types'; import { safeParseInt } from '../utils/safe-parse'; export async function authMiddleware(ctx: Context, next: Next): Promise<void> { // 开发阶段默认跳过认证(除非显式设置 AUTH_ENABLED=true) const authEnabled = process.env.AUTH_ENABLED === 'true'; if (!authEnabled) { ctx.state.user = { userId: '1', phone: 'test', memberLevel: 99, }; await next(); return; } const authHeader = ctx.get('Authorization'); if (!authHeader) { throw new UnauthorizedError('缺少 Authorization 头'); } const parts = authHeader.split(' '); if (parts.length !== 2 || parts[0] !== 'Bearer') { throw new UnauthorizedError('Authorization 格式错误'); } const token = parts[1]; try { const secret = config.jwt.secret; const payload = jwt.verify(token, secret) as JwtPayload; ctx.state.user = payload; await next(); } catch (err: unknown) { const error = err as Error; if (error.name === 'TokenExpiredError') { throw new UnauthorizedError('Token 已过期'); } if (error.name === 'JsonWebTokenError') { throw new UnauthorizedError('Token 无效'); } throw new AppError('认证失败', 401, 401); } } // 可选认证(允许未登录访问,自动使用测试用户) export async function optionalAuth(ctx: Context, next: Next): Promise<void> { const authHeader = ctx.get('Authorization'); if (authHeader) { const parts = authHeader.split(' '); if (parts.length === 2 && parts[0] === 'Bearer') { try { const payload = jwt.verify(parts[1], config.jwt.secret) as JwtPayload; ctx.state.user = payload; } catch { // 忽略错误,使用测试用户 ctx.state.user = { userId: '1', phone: 'test', memberLevel: 99, // 超级VIP }; } } } else { // 没有认证头,使用测试用户(超级VIP) ctx.state.user = { userId: '1', phone: 'test', memberLevel: 99, // 超级VIP }; } await next(); } |