You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:57:42