crush-level-web/src/proxy.ts

126 lines
3.9 KiB
TypeScript
Raw Normal View History

2025-11-28 06:31:36 +00:00
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
2025-11-13 08:38:25 +00:00
// 需要认证的路由
const protectedRoutes = [
2025-11-28 06:31:36 +00:00
'/profile',
'/profile/account',
'/profile/edit',
'/create',
'/settings',
'/login/fields',
'/chat',
'/contact',
'/vip',
'/wallet',
'/wallet/transactions',
'/crushcoin',
]
2025-11-13 08:38:25 +00:00
// 已登录用户不应该访问的路由
2025-11-28 06:31:36 +00:00
const authRoutes = ['/login']
2025-11-13 08:38:25 +00:00
2025-11-28 06:31:36 +00:00
const DEVICE_ID_COOKIE_NAME = 'sd'
2025-11-13 08:38:25 +00:00
// 生成设备ID
function generateDeviceId(userAgent?: string): string {
2025-11-28 06:31:36 +00:00
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'
2025-11-24 03:48:57 +00:00
2025-11-28 06:31:36 +00:00
return `did_${timestamp}_${randomStr}_${browserInfo}`.toLowerCase()
2025-11-13 08:38:25 +00:00
}
2025-12-09 09:13:46 +00:00
export default function proxy(request: NextRequest) {
2025-11-28 06:31:36 +00:00
const { pathname } = request.nextUrl
2025-11-13 08:38:25 +00:00
// console.log('🔄 [MIDDLEWARE] 开始处理路径:', pathname)
// console.log('🔄 [MIDDLEWARE] 请求方法:', request.method)
// console.log('🔄 [MIDDLEWARE] User-Agent:', request.headers.get('user-agent')?.substring(0, 50))
// console.log('🔄 [MIDDLEWARE] 请求头:', Object.fromEntries(request.headers.entries()))
2025-11-24 03:48:57 +00:00
2025-11-13 08:38:25 +00:00
// 获取现有设备ID
2025-11-28 06:31:36 +00:00
let deviceId = request.cookies.get(DEVICE_ID_COOKIE_NAME)?.value
let needSetCookie = false
2025-11-24 03:48:57 +00:00
2025-11-13 08:38:25 +00:00
if (!deviceId) {
// 生成新的设备ID
2025-11-28 06:31:36 +00:00
const userAgent = request.headers.get('user-agent') || undefined
deviceId = generateDeviceId(userAgent)
needSetCookie = true
2025-11-13 08:38:25 +00:00
// console.log('🆕 [MIDDLEWARE] 生成新设备ID:', deviceId)
} else {
2025-11-28 06:31:36 +00:00
console.log('✅ [MIDDLEWARE] 获取现有设备ID:', deviceId)
2025-11-13 08:38:25 +00:00
}
2025-11-24 03:48:57 +00:00
2025-11-13 08:38:25 +00:00
// 认证逻辑
2025-11-28 06:31:36 +00:00
const token = request.cookies.get('st')?.value
const isAuthenticated = !!token
const isProtectedRoute = protectedRoutes.some((route) => pathname.startsWith(route))
2025-11-24 03:48:57 +00:00
const isAuthRoute = authRoutes.some(
2025-11-28 06:31:36 +00:00
(route) => pathname.startsWith(route) && !pathname.startsWith('/login/fields')
)
2025-11-13 08:38:25 +00:00
// console.log('🔑 [MIDDLEWARE] 认证状态:', {
// isAuthenticated,
// pathname,
// isProtectedRoute,
// isAuthRoute,
// token: token ? '存在' : '不存在'
// });
// 如果是受保护的路由但用户未登录,重定向到登录页
if (isProtectedRoute && !isAuthenticated) {
2025-11-28 06:31:36 +00:00
console.log('🚫 [MIDDLEWARE] 重定向到登录页:', pathname)
const loginUrl = new URL('/login', request.url)
loginUrl.searchParams.set('redirect', pathname)
return NextResponse.redirect(loginUrl)
2025-11-13 08:38:25 +00:00
}
// 如果已登录用户访问认证页面,重定向到首页
if (isAuthRoute && isAuthenticated) {
2025-11-28 06:31:36 +00:00
console.log('🔄 [MIDDLEWARE] 已登录用户重定向到首页:', pathname)
return NextResponse.redirect(new URL('/', request.url))
2025-11-13 08:38:25 +00:00
}
// 在请求头中添加认证状态和设备ID供服务端组件使用
2025-11-28 06:31:36 +00:00
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-authenticated', isAuthenticated.toString())
requestHeaders.set('x-device-id', deviceId) // 确保设备ID被传递
2025-11-24 03:48:57 +00:00
2025-11-13 08:38:25 +00:00
if (token) {
2025-11-28 06:31:36 +00:00
requestHeaders.set('x-auth-token', token)
2025-11-13 08:38:25 +00:00
}
// 创建响应
const response = NextResponse.next({
request: {
headers: requestHeaders,
2025-11-24 03:48:57 +00:00
},
2025-11-28 06:31:36 +00:00
})
2025-11-13 08:38:25 +00:00
// 如果需要设置设备ID cookie
if (needSetCookie) {
response.cookies.set(DEVICE_ID_COOKIE_NAME, deviceId, {
maxAge: 365 * 24 * 60 * 60, // 365天
httpOnly: false,
2025-11-28 06:31:36 +00:00
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
})
2025-11-13 08:38:25 +00:00
}
2025-11-28 06:31:36 +00:00
if (pathname.startsWith('/@')) {
const userId = pathname.slice(2) // 去掉/@
return NextResponse.rewrite(new URL(`/user/${userId}`, request.url))
2025-11-13 08:38:25 +00:00
}
2025-11-28 06:31:36 +00:00
console.log('✅ [MIDDLEWARE] 成功处理完毕:', pathname)
return response
2025-11-13 08:38:25 +00:00
}
export const config = {
matcher: [
// 匹配所有路径除了静态文件和API路由
2025-11-28 06:31:36 +00:00
'/((?!api|_next/static|_next/image|favicon.ico|public).*)',
2025-11-13 08:38:25 +00:00
],
2025-11-28 06:31:36 +00:00
}