import { NextResponse, type NextRequest } from 'next/server'; import { authConfig, SESSION_COOKIE, validSession } from './lib/auth'; export function proxy(request: NextRequest) { const path = request.nextUrl.pathname; const responseHeaders = {'Cache-Control':'private, no-store', 'Referrer-Policy':'same-origin'}; // Public knowledge pages are read-only. Account handlers enforce their own origin and session checks. const publicRead = ['GET','HEAD'].includes(request.method) && (path === '/' || path === '/protocol' || path.startsWith('/guide/') || path.startsWith('/api/guides/')); if (publicRead || path === '/account' || path.startsWith('/api/account/')) return NextResponse.next({headers:{...responseHeaders,'Referrer-Policy':'no-referrer'}}); if (path === '/brand-mark.svg' || path === '/login' || path === '/api/auth/login' || path === '/api/auth/logout' || path === '/api/health' || path === '/api/ready' || path.startsWith('/_next/static/')) return NextResponse.next({headers:responseHeaders}); let config; try { config = authConfig(); } catch { return NextResponse.json({error:'登录服务配置不可用'}, {status:503,headers:responseHeaders}); } if (!config) { if (process.env.AUTH_DISABLED_FOR_TESTS === 'true' && process.env.AUTH_CONFIG_FILE === '') return NextResponse.next(); return NextResponse.json({error:'管理员登录服务尚未配置'}, {status:503,headers:responseHeaders}); } const bearer = request.headers.get('authorization'); const token = bearer?.startsWith('Bearer ') ? bearer.slice(7) : request.cookies.get(SESSION_COOKIE)?.value; if (validSession(token,config)) { if (!['GET','HEAD','OPTIONS'].includes(request.method) && !bearer) { const origin = request.headers.get('origin'); const host = request.headers.get('host'); try { if (!origin || new URL(origin).host !== host || request.headers.get('sec-fetch-site') === 'cross-site') return NextResponse.json({error:'请求来源不受信任'}, {status:403,headers:responseHeaders}); } catch { return NextResponse.json({error:'请求来源不受信任'}, {status:403,headers:responseHeaders}); } } return NextResponse.next({headers:responseHeaders}); } if (path.startsWith('/api/') || path.startsWith('/studio/api/') || !['GET','HEAD'].includes(request.method)) return NextResponse.json({error:'请先使用动态码登录'}, {status:401,headers:responseHeaders}); const login = request.nextUrl.clone(); login.pathname = '/login'; login.search = ''; login.searchParams.set('next',path + request.nextUrl.search); return NextResponse.redirect(login,{headers:responseHeaders}); }