Next.js 13.4中间件中如何用Fetch API携带Cookie实现授权?
在Next.js 13.4中间件里没法用Axios,改用Fetch API做授权时碰到Cookie发不出去的问题。知道Fetch默认不发Cookie,已经加了credentials: include选项,但还是没用。
下面是Next.js中间件代码:
import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; const getUserRole = async function () { try { const res = await fetch("http://localhost:8080/auth/me", { method: "GET", headers: { Accept: "application/json", "Content-Type": "application/json", }, credentials: "include", }); if (res && res.status === 200) { return res.json(); } else { console.error("Request failed"); } } catch (error) { console.error('Request to "auth/me" failed', error); } }; export function middleware(request: NextRequest) { const path = request.nextUrl.pathname; const isPublicPath = path === "/auth/login" || path === "/auth/register" || path === "/"; const token = request.cookies.get("access_token")?.value || ""; if (isPublicPath && token && path !== "/") { return NextResponse.redirect(new URL("/", request.nextUrl)); } if (!isPublicPath && !token) { return NextResponse.redirect(new URL("/auth/login", request.nextUrl)); } if (!isPublicPath && token) { console.log("tokkk :", token); getUserRole().then((res: any) => { console.log("role ::", res); }); } } export const config = { matcher: ["/", "/auth/login", "/auth/register", "/dashboard"], };
Nest.js后端CORS配置:
app.enableCors({ origin: 'http://localhost:3000', allowedHeaders: [ 'Content-Type', 'Authorization', 'X-Requested-With', 'X-HTTP-Method-Override', 'Content-Type', 'Accept', 'Observe', 'Access-Control-Allow-Credentials', 'Access-Control-Allow-Origin', 'Access-Control-Allow-Headers', ], methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS', credentials: true, });
解决方法
1. 核心问题:中间件运行在服务器端,无浏览器Cookie上下文
Next.js中间件是在服务器环境运行的,不是浏览器端。你加的credentials: include只对浏览器端Fetch生效,服务器端Fetch没有浏览器的Cookie存储上下文,自然没法自动携带Cookie。而你在中间件里拿到的token是从当前请求的Cookie中获取的,需要手动传给Fetch请求。
2. 修改Fetch请求,手动携带Cookie
把getUserRole改成接收token参数,手动设置Cookie请求头:
const getUserRole = async function (token: string) { try { const res = await fetch("http://localhost:8080/auth/me", { method: "GET", headers: { Accept: "application/json", "Content-Type": "application/json", // 手动将token放入Cookie请求头 "Cookie": `access_token=${token}` }, // 服务器端Fetch无需credentials选项,可删除 }); if (res && res.status === 200) { return res.json(); } else { console.error("Request failed"); } } catch (error) { console.error('Request to "auth/me" failed', error); } };
然后在中间件调用时传入token:
if (!isPublicPath && token) { console.log("tokkk :", token); getUserRole(token).then((res: any) => { console.log("role ::", res); }); }
3. 优化Nest.js的CORS配置
你的CORS配置里allowedHeaders混入了响应头(比如Access-Control-Allow-Credentials),这些是服务器返回给浏览器的响应头,不需要放在允许的请求头列表里,可精简为:
app.enableCors({ origin: 'http://localhost:3000', allowedHeaders: [ 'Content-Type', 'Authorization', 'X-Requested-With', 'X-HTTP-Method-Override', 'Accept', 'Observe', ], methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS', credentials: true, });
4. 检查Cookie的SameSite属性
如果后端设置access_token时,SameSite属性设为Strict或Lax,跨域场景下可能导致Cookie无法发送。建议后端设置Cookie时:
- 优先用
SameSite: 'Lax'(默认值,适配大部分场景) - 若需跨域第三方Cookie,设
SameSite: 'None',但必须同时添加Secure: true(仅HTTPS环境生效)
内容的提问来源于stack exchange,提问作者Behnam
相关产品推荐
相关产品推荐

