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
相关产品推荐
相关产品推荐

