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

NextJS与NestJS中JWT验证及受保护路由问题求助

问题背景

我正在开发一款全栈应用,后端基于NestJS实现,前端采用NextJS。后端认证功能已正常运行,前端也实现了仅允许登录用户访问的路由保护逻辑,但目前存在一个问题:只要在浏览器Cookie中设置伪造的token,就能直接访问受保护路由。

相关代码

后端登录实现

后端登录代码截图

前端登录逻辑

const handleLogin = async (e: FormEvent) => {
    e.preventDefault();

    try {
      const response = await axios.post<string>(
        "http://localhost:3003/auth/administrare-site", // Replace with your backend API endpoint
        formData
      );

      // Assuming your backend returns a token on successful login
      const token = response.data;

      // Store the token in local storage or a cookie for future requests
      Cookies.set("token", JSON.stringify(token), {
        expires: 7,
        secure: true,
        sameSite: "strict",
      });


      // Redirect to the dashboard page
      router.push("/dashboard");
    } catch (error) {
      console.error("Error:", error);
    }
  };

前端路由保护中间件

function requireAuth<T extends JSX.IntrinsicAttributes>(
  Component: React.ComponentType<T>
) {
  return (props: T) => {
    const router = useRouter();

    // Check if the 'token' cookie is present
    const tokenString = Cookies.get("token");
    let token = tokenString;


    console.log(token);
    if (!token) {
      // Redirect to the login page if the token is not present
      console.log('failed')
      router.push("/administrare-site");
      return null;
    }
   
    console.log('good')
    // Render the protected component if the token is present and valid
    return <Component {...props} />;
  };
}

export default requireAuth;

路由保护使用方式

export default requireAuth(Dashboard);

核心疑问

当前前端仅检查Cookie中是否存在token,未对token的有效性进行验证,且不清楚如何在不暴露JWT_SECRET的前提下完成token验证,恳请提供帮助。


解决方案

1. 核心原则:前端绝不直接验证JWT

JWT的有效性验证必须放在后端完成,绝对不能在前端暴露JWT_SECRET——前端完全不可信,任何密钥放在前端都会被轻易获取。

2. 后端新增token验证接口

在NestJS后端新增一个接口,比如GET /auth/validate-token,利用NestJS的JWT Guard自动验证token:

// NestJS auth controller
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller('auth')
export class AuthController {
  // 依赖已配置好的JWT策略,自动验证请求头中的token
  @Get('validate-token')
  @UseGuards(AuthGuard('jwt'))
  validateToken(@Req() req) {
    // 验证通过后返回用户信息或成功标识
    return { valid: true, user: req.user };
  }
}

确保你的NestJS项目已经正确配置了@nestjs/jwt和passport-jwt,策略中使用JWT_SECRET解析token。

3. 修改前端路由保护逻辑,调用后端验证接口

更新requireAuth中间件,在检测到token存在后,调用后端接口确认token有效性:

import axios from 'axios';
import { useEffect, useState } from 'react';

function requireAuth<T extends JSX.IntrinsicAttributes>(
  Component: React.ComponentType<T>
) {
  return (props: T) => {
    const router = useRouter();
    const [isTokenValid, setIsTokenValid] = useState<boolean | null>(null);
    const tokenString = Cookies.get("token");
    const token = tokenString ? JSON.parse(tokenString) : null;

    useEffect(() => {
      const validateToken = async () => {
        if (!token) {
          router.push("/administrare-site");
          return;
        }

        try {
          await axios.get("http://localhost:3003/auth/validate-token", {
            headers: {
              Authorization: `Bearer ${token}`
            }
          });
          setIsTokenValid(true);
        } catch (error) {
          // 验证失败,清除无效token并跳转登录页
          Cookies.remove("token");
          router.push("/administrare-site");
          setIsTokenValid(false);
        }
      };

      validateToken();
    }, [token, router]);

    // 加载状态可替换为自定义加载组件
    if (isTokenValid === null) {
      return <div>加载中...</div>;
    }

    return isTokenValid ? <Component {...props} /> : null;
  };
}

export default requireAuth;

4. 安全优化建议

  • 改用HttpOnly Cookie存储token:当前用的普通Cookie可被前端JS读取,改成HttpOnly Cookie(后端设置)能防止XSS攻击窃取token。NestJS设置示例:
    // 登录接口返回时设置HttpOnly Cookie
    res.cookie('token', jwtToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'strict',
      maxAge: 7 * 24 * 60 * 60 * 1000 // 7天有效期
    });
    
  • 前端无需手动存储token:使用HttpOnly Cookie后,前端登录后不需要自己存token,后续请求会自动携带Cookie,后端直接从Cookie中获取token验证。
  • 前端提前判断token过期:可以解析JWT的payload(base64编码,无需密钥),读取exp字段提前判断token是否过期,减少无效请求。

内容的提问来源于stack exchange,提问作者palalele

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 11:00:27