HTTPS环境下JWT Cookie无法在Next.js前端显示问题求助
我在实现Google登录功能,通过Cookie传递JWT Token给Next.js前端,用于中间件校验受保护路由。本地localhost环境一切正常,Token能正常设置为Cookie;但切换到HTTPS开发环境后,后端能生成JWT,但浏览器Application-Cookie里看不到这个Token,中间件无法读取Token完成受保护路由跳转。
后端登录接口代码
import { Router } from 'express'; import passport from 'passport'; import User from '../models/User'; // Ensure this path is correct for your project structure import jwt from 'jsonwebtoken'; import cookie from 'cookie'; import dotenv from 'dotenv'; dotenv.config(); const router = Router(); //router.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] })); router.get('/creator', passport.authenticate('google-content-creator', { accessType: 'offline', prompt: 'consent', scope: [ 'profile', 'email', // Add any other scopes needed for YouTube here 'https://www.googleapis.com/auth/youtube', 'https://www.googleapis.com/auth/youtube.force-ssl' ] } as any)); router.get('/google/redirect', passport.authenticate('google-content-creator', { failureRedirect: '/login' }), async (req, res) => { if (req.user) { const { googleId, email, name } = req.user as any; // Type casting for simplicity try { // Check if the user already exists let user = await User.findOne({ googleId }); if (user) { user.isContentCreator = true; await user.save(); } else { user = new User({ googleId, email, name, isContentCreator: true }); await user.save(); } // Create a token object const tokenData = { _id: user._id, email: user.email, googleId: user.googleId, name:user.name }; const tokenSecret = process.env.JWT_SECRET as string const token = jwt.sign(tokenData, tokenSecret, { expiresIn: "1d" }); console.log("token",token) // Set token in cookies res.setHeader('Set-Cookie', cookie.serialize('token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', path: '/', maxAge: 60 * 60 * 24 // 24 hours })); const creatorId = user._id console.log('Redirecting to dashboard of content creator...'); res.redirect(`${process.env.CREATOR_CLIENT_URL}/${creatorId}/contentCreatorDashboard`); } catch (error) { console.error('Error handling user login:', error); res.status(500).send('Internal Server Error'); } } else { console.log('User authentication failed, redirecting to login...'); res.redirect('/login'); } }); export default router;
前端Next.js中间件代码
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import { cookies } from 'next/headers'; export async function middleware(request: NextRequest) { const cookieData = cookies().getAll(); const token = cookieData.find(cookie => cookie.name === 'token')?.value; const path = request.nextUrl.pathname; // Adjust the paths as needed const isPublicPath = ['/login', '/signup', '/verifyemail'].includes(path); if (!token && !isPublicPath) { // User is not logged in and trying to access a protected route return NextResponse.redirect(new URL('/login', request.url)); } // If the user is trying to access login-related routes but is already authenticated if (token && isPublicPath) { return NextResponse.redirect(new URL('/fetchUser', request.url)); } // Allow the request to continue return NextResponse.next(); } export const config = { matcher: [ `/:path*/contentCreatorDashboard`, `/login`, `/signup`, `/verifyemail`, `/test`, `/:path*/campaigns`, `/:path*/campaigns/campaignAnalytics/:path*`, `/:path*/leaderBoard`, `/fetchUser`, '/:path*/leaderBoard/:path*' ], // Adjust based on your route requirements };
问题原因与解决办法
1. Cookie的secure属性配置问题
当前代码中secure仅在production环境设为true,但HTTPS开发环境不属于production,导致secure为false。HTTPS环境下浏览器会拒绝保存secure: false的Cookie。
修复代码:
修改Cookie配置,让secure在HTTPS环境下自动生效:
res.setHeader('Set-Cookie', cookie.serialize('token', token, { httpOnly: true, secure: req.protocol === 'https' || process.env.NODE_ENV === 'production', path: '/', maxAge: 60 * 60 * 24, // 24 hours sameSite: 'lax' // 补充SameSite属性,避免跨站Cookie限制 }));
2. 补充SameSite属性
HTTPS环境下浏览器对Cookie的SameSite属性要求更严格,缺失可能导致Cookie不被保存。根据跨域需求选择lax(允许同站/部分跨站请求携带)或strict(仅同站请求携带)。
3. 跨域场景下配置domain属性
如果前后端域名不同(如后端是api.example.com,前端是example.com),需添加domain属性确保Cookie能被前端域名读取:
domain: process.env.COOKIE_DOMAIN || '.example.com', // 前缀点号适配子域名
4. 检查浏览器Cookie设置
确保浏览器未阻止第三方Cookie,开发环境下可临时允许所有Cookie测试。
内容的提问来源于stack exchange,提问作者Prajyan Borah
相关产品推荐
相关产品推荐

