Next.js中间件设置Auth Cookie无效问题排查
我在Next.js中编写了一个中间件,用于拦截URL中的OTP(一次性验证码),验证通过后设置Auth Cookie,避免用户被重定向到登录页。但执行重定向后,Cookie并未生效,相关代码与日志如下,请问原因是什么?
中间件代码
/** * Intercept every request and auth OTP if required */ export async function middleware(request: NextRequest) { const url = request.nextUrl.clone() const otp = url.searchParams.get('otp') console.log("middleware request: " + url); // if there is an OTP and no auth authorise if (otp) { console.log("middleware, authenticating with OTP: " + otp); url.searchParams.delete('otp') const response = NextResponse.redirect(url) const cookieStore = await cookies(); const auth = cookieStore.get("auth"); if (auth === undefined) { const API_URL = nextConfig?.env?.API_URL as string; const {data} = await axios.post(`${API_URL}/otp`, {otp}); if (data) { const authJson = JSON.stringify(data); console.log("middleware, setting auth cookie from OTP: " + authJson) response.cookies.set("auth", authJson, {expires: 30, /* 30 days */ path: "/"}); } return response; } } else { const cookieStore = await cookies(); const auth = cookieStore.get("auth"); console.log("middleware, auth=true", auth); } return NextResponse.next() }
日志信息
middleware request: http://localhost:3000/boardruns/edit/1?otp=1234 middleware, authenticating with OTP: 1234 middleware, setting auth cookie from OTP: {"name":"name name","email":"boardrunner@boardrunner.com","roles":["ROLE_USER"],"jwt":"eyJhbG.....hJxVLc"} middleware request: http://localhost:3000/boardruns/edit/1 middleware, auth=true undefined
核心原因分析
- Cookie的
expires参数格式错误:你设置的expires: 30是无效值,Next.js的response.cookies.set要求expires必须是Date对象,而非数字。这个错误会导致浏览器无法识别Cookie的过期时间,进而不会保存该Cookie,所以重定向后的请求读取不到auth Cookie。 - 重定向后的请求无Cookie:第一次请求中虽然代码执行了设置Cookie的逻辑,但因为参数错误,浏览器未存储Cookie,导致第二次请求(重定向后的URL)的CookieStore中没有auth条目。
修复方案
方案1:修正expires参数为Date对象
将expires: 30替换为计算30天后的Date实例:
response.cookies.set("auth", authJson, { expires: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30天后的时间 path: "/" });
方案2:改用maxAge参数(更直观)
maxAge以秒为单位设置Cookie有效期,无需手动计算Date:
response.cookies.set("auth", authJson, { maxAge: 30 * 24 * 60 * 60, // 30天对应的秒数 path: "/" });
内容的提问来源于stack exchange,提问作者Essex Boy
相关产品推荐
相关产品推荐

