import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; // 需要认证的路由 const protectedRoutes = [ '/profile', '/profile/account', '/profile/edit', '/settings', '/login/fields', '/chat', '/contact', '/vip', '/wallet', '/wallet/transactions', '/crushcoin', ]; // 已登录用户不应该访问的路由 const authRoutes = ['/login']; const DEVICE_ID_COOKIE_NAME = 'sd'; // 生成设备ID function generateDeviceId(userAgent?: string): string { const timestamp = Date.now().toString(36); const randomStr = Math.random().toString(36).substring(2, 15); const browserInfo = userAgent ? userAgent.replace(/\s/g, '').substring(0, 10) : 'server'; return `did_${timestamp}_${randomStr}_${browserInfo}`.toLowerCase(); } export default function proxy(request: NextRequest) { const { pathname } = request.nextUrl; // 获取现有设备ID let deviceId = request.cookies.get(DEVICE_ID_COOKIE_NAME)?.value; let needSetCookie = false; if (!deviceId) { // 生成新的设备ID const userAgent = request.headers.get('user-agent') || undefined; deviceId = generateDeviceId(userAgent); needSetCookie = true; } else { // console.log('✅ [MIDDLEWARE] 获取现有设备ID:', deviceId); } // 认证逻辑 const token = request.cookies.get('st')?.value; const isAuthenticated = !!token; const isProtectedRoute = protectedRoutes.some((route) => pathname.startsWith(route)); const isAuthRoute = authRoutes.some( (route) => pathname.startsWith(route) && !pathname.startsWith('/login/fields') ); // 如果是受保护的路由但用户未登录,重定向到登录页 if (isProtectedRoute && !isAuthenticated) { console.log('🚫 [MIDDLEWARE] 重定向到登录页:', pathname); const loginUrl = new URL('/login', request.url); loginUrl.searchParams.set('redirect', pathname); return NextResponse.redirect(loginUrl); } // 如果已登录用户访问认证页面,重定向到首页 if (isAuthRoute && isAuthenticated) { console.log('🔄 [MIDDLEWARE] 已登录用户重定向到首页:', pathname); return NextResponse.redirect(new URL('/', request.url)); } // 在请求头中添加认证状态和设备ID,供服务端组件使用 const requestHeaders = new Headers(request.headers); requestHeaders.set('x-authenticated', isAuthenticated.toString()); requestHeaders.set('x-device-id', deviceId); // 确保设备ID被传递 if (token) { requestHeaders.set('x-auth-token', token); } // 创建响应 const response = NextResponse.next({ request: { headers: requestHeaders, }, }); // 如果locale cookie不存在,设置为en-US if (!request.cookies.get('locale')?.value) { response.cookies.set('locale', 'en-US', { maxAge: 365 * 24 * 60 * 60, // 365天 httpOnly: false, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', path: '/', }); } // 如果需要设置设备ID cookie if (needSetCookie) { response.cookies.set(DEVICE_ID_COOKIE_NAME, deviceId, { maxAge: 365 * 24 * 60 * 60, // 365天 httpOnly: false, secure: process.env.NODE_ENV === 'production', sameSite: 'lax', path: '/', }); } return response; } export const config = { matcher: [ // 匹配所有路径,除了静态文件和API路由 '/((?!api|_next/static|_next/image|favicon.ico|public).*)', ], };