Next.js中间件无法获取已设置的access_token Cookie问题排查
用户在localhost:3000/auth页面登录后,后端成功返回并在Cookie中设置了access_token,前端登录成功后重定向到/protected页面触发中间件,但中间件中始终获取不到Cookie(开发者工具能看到Cookie已存在)。
前端中间件代码(middleware.ts)
const protectedRoutes = ['/protected']; export async function middleware(request: NextRequest) { const { cookies, nextUrl } = request; const test = request.cookies.get('access_token') console.log(request) if (!cookies) { return "prout" } const accessToken = cookies.get('access_token'); const isProtected = protectedRoutes.includes(nextUrl.pathname); if (isProtected && !accessToken) { return NextResponse.redirect(new URL('/auth', request.url)); } console.log(nextUrl.pathname) if (nextUrl.pathname === '/auth' && accessToken) { return NextResponse.redirect(new URL('/protected', request.url)); } return NextResponse.next(); } export const config = { matcher: ['/auth', '/protected'], };
前端登录提交逻辑
const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); try { const response = await loginUser(form); console.log(response) // setForm({ username: "", password: "" }); router.push('/protected') } catch (error: any) { console.log(error) setError("Registration error: " + error.message); } };
后端登录接口代码(Python/FastAPI)
async def login_user(db: AsyncSession, username: str, password: str): """ check if correct credentials and return bearer token """ user = await get_user_by_username(db, username) if not user or not verify_password(password, user.password): time.sleep(3) raise HTTPException(status_code=401, detail="Invalid credentials") access_token = create_access_token( {"sub": user.username}, timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) ) refresh_token = create_refresh_token( {"sub": user.username}, expires_delta=timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS) ) csrf_token = generate_csrf_token() response = JSONResponse(content={"message": "Login successful"}) response.set_cookie( key="access_token", value=access_token, httponly=True, path='/', samesite='none', secure=True ) response.set_cookie( key="refresh_token", value=refresh_token, path='/', # TODO /refresh httponly=True, samesite='none', secure=True ) response.set_cookie( key="csrf_token", value=csrf_token, httponly=False, path='/', samesite='none', secure=True ) return response
原因分析
问题核心出在Cookie的secure: true和samesite: none配置:
secure: true限制:该配置要求Cookie只能通过HTTPS协议传输,但你当前使用的是localhost:3000(HTTP协议),浏览器不会把HTTPS专属的Cookie发送到HTTP站点,导致中间件获取不到。samesite: none的配套要求:当samesite设为none时,必须同时设置secure: true,但本地开发环境是HTTP,这直接导致Cookie无法被正确传递到中间件。
Next.js中间件运行在服务器端/边缘节点,它接收的是浏览器请求头里的Cookie,若浏览器因协议限制未携带Cookie,中间件自然拿不到。
解决方案
针对本地开发环境,修改后端Cookie配置:
- 保留
httponly: true和path: '/',调整samesite和secure参数:response.set_cookie( key="access_token", value=access_token, httponly=True, path='/', samesite='lax', # 本地开发用lax或strict secure=False # 本地HTTP环境设为false ) - 生产环境再改回
samesite: 'none'和secure: true,确保HTTPS环境下的跨域Cookie正常工作。
若需要模拟生产环境,也可以在本地启用HTTPS(比如用mkcert生成证书),这样就能保留secure: true配置,但操作相对繁琐。
内容的提问来源于stack exchange,提问作者El Pandario
相关产品推荐
相关产品推荐

