Next.js 12 API路由中无法获取Cookie的问题求助
问题原因
当你在getServerSideProps中用fetch调用内部API路由时,这个请求是服务器端发起的,默认不会携带客户端浏览器的Cookie。而直接访问API路由时,请求来自浏览器,浏览器会自动带上当前域名下的Cookie,所以后端能正常获取。
解决方案
有两种可行的处理方式,根据你的需求选择:
方案1:直接在getServerSideProps中查询数据库(推荐)
既然getServerSideProps本身就在服务器端运行,没必要多一次内部API请求,直接在这里验证Cookie并查询用户的任务:
// src/pages/tasks/index.js import mongoose from 'mongoose'; import Task from '../../models/Task'; // 你的Task模型 import { jwtVerify } from "jose"; export async function getServerSideProps(context) { // 从context中获取客户端的Cookie const { userAuthToken } = context.req.cookies; if (!userAuthToken) { return { redirect: { destination: '/login', permanent: false, }, }; } try { // 验证JWT const { payload } = await jwtVerify(userAuthToken, new TextEncoder().encode("secret")); // 连接数据库(如果还没连接) if (!mongoose.connections[0].readyState) { await mongoose.connect(process.env.MONGODB_URI); } // 查询当前用户的任务 const tasks = await Task.find({ userId: payload.userId }); return { props: { tasks: JSON.parse(JSON.stringify(tasks)) } // 转换为可序列化的JSON }; } catch (error) { console.error(error); return { redirect: { destination: '/login', permanent: false, }, }; } }
方案2:手动传递Cookie到fetch请求
如果你坚持要通过API路由获取数据,需要把getServerSideProps中拿到的Cookie手动添加到fetch的请求头里:
// src/pages/tasks/index.js export async function getServerSideProps(context) { const URL = process.env.NEXT_PUBLIC_TASKS_API_URL; // 从context.req中获取客户端的Cookie const cookies = context.req.headers.cookie; const response = await fetch(URL, { headers: { // 把Cookie传递给API路由 Cookie: cookies || '' } }); const tasks = await response.json(); return { props: { tasks: tasks.error ? [] : tasks } }; }
同时,确保你的API路由能正确解析Cookie(Next.js 12中req.cookies是自动解析的,只要请求头里有Cookie就可以拿到):
// src/pages/api/tasks/index.js export default async function handler(req, res) { const { method, cookies } = req; const { userAuthToken } = cookies; if (!userAuthToken) { return res.status(401).json({ error: '未授权' }); } // 后续验证JWT、查询数据库逻辑... }
额外提示
- 不要在JWT中存储密码!JWT是可明文解码的,存储密码会导致安全问题,只需要存用户ID、用户名这类非敏感信息即可。
- 中间件已经在做身份验证,
getServerSideProps或API路由里的验证可以作为二次校验,确保安全性。
内容的提问来源于stack exchange,提问作者Genaro Bonavita
相关产品推荐
相关产品推荐

