export default defineEventHandler((event) => { const pathname = getRequestURL(event).pathname // 只处理特定的内部API路由,防止站外调用 const isProtectedApi = pathname.startsWith('/api/api-enhanced/netease') || pathname.startsWith('/api/native-api') if (!isProtectedApi) { return } // CORS 限制:禁止站外网站调用 const origin = getHeader(event, 'origin') const referer = getHeader(event, 'referer') const secFetchSite = getHeader(event, 'sec-fetch-site') const sourceUrl = origin || referer if (sourceUrl) { try { const url = new URL(sourceUrl) const extractHostname = (value: string) => { const normalizedValue = value.includes('://') ? value : `http://${value}` return new URL(normalizedValue).hostname } // 获取当前请求的 hostname,优先使用配置中可信的主机名,防止 x-forwarded-host 伪造攻击 const config = useRuntimeConfig(event) const configuredHost = config.public?.host let requestHostname: string if (configuredHost) { requestHostname = extractHostname(configuredHost) } else { // 只有在未配置公网主机名时,才回退到 host 请求头 const hostHeader = getHeader(event, 'host') if (hostHeader) { requestHostname = extractHostname(hostHeader) } else { // 缺少 Host 请求头,这是一个异常情况,应该拒绝请求 throw createError({ statusCode: 400, message: 'Bad Request: 缺少Host请求头' }) } } const isLocalhost = (h: string) => h === 'localhost' || h === '127.0.0.1' || h === '[::1]' // 如果来源域与当前域不一致,则拒绝请求 // 注意:允许 localhost 和 127.0.0.1 之间的互访 if (url.hostname !== requestHostname && !(isLocalhost(url.hostname) && isLocalhost(requestHostname))) { console.warn(`[CORS Middleware] 拦截跨域请求: 来源 ${url.hostname}, 期望 ${requestHostname}, 路径 ${pathname}`) throw createError({ statusCode: 403, message: 'Forbidden: 内部API不允许跨域请求' }) } } catch (e: unknown) { // 如果是我们主动抛出的 HTTP 错误,则重新抛出 if ( typeof e === 'object' && e !== null && 'statusCode' in e && typeof e.statusCode === 'number' ) { throw e } // 对于其他错误(如无效的URL),这是一个错误的请求 console.warn(`[CORS Middleware] 无效的来源 URL: ${sourceUrl}`, e) throw createError({ statusCode: 400, message: 'Bad Request: Origin或Referer头无效' }) } } else if (secFetchSite === 'same-origin') { // 允许没有 Origin/Referer 但明确标记为同源的请求 return } else { // 拦截没有来源信息的受保护API请求 console.warn(`[CORS Middleware] 拦截无Origin/Referer头的请求: 路径 ${pathname}, sec-fetch-site: ${secFetchSite || 'none'}`) throw createError({ statusCode: 403, message: 'Forbidden: 访问此API必须提供Origin或Referer头' }) } })