Next.js API路由可被外部访问?CORS未生效问题求助
问题分析与解决方案
为什么Postman还能访问你的API?
你配置的CORS头是浏览器专属的安全机制,只有浏览器在发起跨域请求时才会校验这些规则。Postman、curl这类非浏览器客户端根本不会遵守CORS限制,它们会直接发送请求并接收响应,所以你的CORS配置管不了这类工具。
你的配置哪里没到位?
你的CORS配置仅能限制浏览器的跨域行为,但如果要实现真正的仅允许同源访问(不管客户端类型),光靠Next.js的headers配置是不够的——必须在API路由里添加Origin验证逻辑,主动拒绝不符合要求的请求。
实现仅同源访问的具体方案
方案1:用Next.js中间件统一验证(推荐)
在项目根目录创建middleware.ts(或.js),统一拦截所有API请求并验证Origin:
import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' export function middleware(request: NextRequest) { // 允许OPTIONS预检请求通过 if (request.method === 'OPTIONS') { return NextResponse.next() } // 获取请求的Origin const requestOrigin = request.headers.get('origin') // 定义允许的Origin列表 const allowedOrigins = [ process.env.NODE_ENV === 'production' ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000' ] // 验证Origin是否合法 if (!requestOrigin || !allowedOrigins.includes(requestOrigin)) { return new NextResponse('Not allowed', { status: 403 }) } // 验证通过,继续处理请求 return NextResponse.next() } // 指定拦截的API路由范围 export const config = { matcher: '/api/:path*', }
方案2:在单个API路由里添加验证
如果不想用中间件,也可以在每个API路由文件里手动添加验证逻辑:
export default function handler(req, res) { // 处理OPTIONS预检请求 if (req.method === 'OPTIONS') { res.setHeader('Access-Control-Allow-Credentials', 'true') res.setHeader('Access-Control-Allow-Origin', process.env.NODE_ENV === 'production' ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000') res.setHeader('Access-Control-Allow-Methods', 'GET,OPTIONS,PATCH,DELETE,POST,PUT') res.setHeader('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version') return res.status(200).end() } // 验证请求Origin const requestOrigin = req.headers.origin const allowedOrigin = process.env.NODE_ENV === 'production' ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000' if (!requestOrigin || requestOrigin !== allowedOrigin) { return res.status(403).json({ message: 'Not allowed' }) } // 正常处理API业务逻辑 res.status(200).json({ data: 'Your response data' }) }
注意事项
- Vercel生产环境会自动注入
VERCEL_URL变量,无需手动配置;开发环境要确保Origin带上http://前缀,否则匹配会失败。 - 必须单独处理
OPTIONS预检请求,否则浏览器的跨域请求会直接失败。
内容的提问来源于stack exchange,提问作者Adib Kadir
相关产品推荐
相关产品推荐

