You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTTPS环境下JWT Cookie无法在Next.js前端显示问题求助

问题: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:27:35