我正在开发一个 PERN 项目,使用 JWT 令牌进行授权。目前,我遇到了这样的问题,即具有过期 JWT 令牌的用户将停留在同一页面上,并显示一条 toast 错误消息,指出“授权中的错误:令牌已过期”。
我希望我的用户被重定向到 /partner/login,并清除本地存储并在检测到过期令牌时显示 toast 消息。
但是,就我而言,FE 知道 JWT 令牌已经过期,因为打印了 console.log('expiredddddd') 但序列行无法正常工作,因为未显示 toast 消息,localStorage 不清楚,用户未重定向到
/partner/login
。用户必须刷新手动页面才能重定向到 /partner/login
。有谁可以帮忙看看这个问题吗?
import React, { useEffect } from "react";
import { Navigate, Outlet } from "react-router-dom";
import Spinner from "../utils/Spinner";
import toast from "react-hot-toast";
import { jwtDecode } from "jwt-decode";
const AuthenticatedRoute = ({
isAuthenticated,
loading,
isLoggingOut, // New prop to indicate if the user is logging out
}) => {
const token = localStorage.getItem("token");
useEffect(() => {
// Check if token exists and is not expired
if (token) {
const decodedToken = jwtDecode(token);
const currentTime = Date.now() / 1000; // Convert milliseconds to seconds
if (decodedToken.exp < currentTime) {
// Token expired
console.log("expiredddddd"); // this was printed but sequence lines got ignored
toast.error("Your session has expired. Please log in again.");
localStorage.clear(); // Remove expired token
return <Navigate to="/partner/login" />;
}
}
}, [token]);
// Check if there is no token and the user is not authenticated
if (!token && !isAuthenticated && !isLoggingOut) {
toast.error("You have not logged in");
return <Navigate to="/partner/login" />;
}
// Check if the user is not authenticated and loading is complete
if (!isAuthenticated && !loading && !isLoggingOut) {
toast.error("You have not logged in");
return <Navigate to="/partner/login" />;
}
// Show loading spinner while authentication status is being determined
if (loading) {
return <Spinner />;
}
// Render the child routes if the user is authenticated
return <Outlet />;
};
export default AuthenticatedRoute;
这是我的中间件
const jwt = require("jsonwebtoken");
require("dotenv").config();
module.exports = async (req, res, next) => {
// get token and method from header
const authHeader = req.headers.authorization;
if (authHeader) {
// Split the authorization header into parts
const parts = authHeader.split(" ");
if (parts.length === 2 && parts[0] === "Bearer") {
const jwtToken = parts[1]; // Extract the token from the header
try {
const payload = jwt.verify(jwtToken, process.env.jwtSecret);
req.user = payload.user; // Attach user data to request object
next();
} catch (err) {
if (err instanceof jwt.TokenExpiredError) {
return res
.status(401)
.json({ error: "ERROR in Authorization: Token expired" });
// I was able to see this message
} else if (err instanceof jwt.JsonWebTokenError)
return res
.status(401)
.json({ error: "ERROR in Authorization: Invalid JWT" });
return res
.status(500)
.json({ error: "ERROR in Authorization: Server error" });
}
} else {
// Invalid authorization header format
return res.status(401).json({ error: "Invalid authorization header" });
}
} else {
// Authorization header not present
return res.status(401).json({ error: "Authorization header missing" });
}
};
您无法通过返回
useEffect()
中的组件来直接操作渲染。
相反,请尝试在
isExpired
中设置状态 useEffect()
,然后在 useEffect()
之外设置状态 <Navigate to="/partner/login" />
(如果 isExpired
为 true)。