我已经创建了一个安全路由/秘密,在我的反应应用程序中使用反应路由器,当有人登录时,我的应用程序通过 jwt 创建一个 cookie 并将其存储在用户的浏览器中,当有人点击此/秘密路由时,我的前端共享以下信息使用我的后端令牌并验证它是否有效(使用 jwt.verify),如果经过验证,我的后端会以状态 200 进行响应,我的前端将授予其查看 /secret 的权限,如果用户未经过验证,他将被重定向到 /login 路由再次登录。我已经使用 useState 使用 React 的 useEffect 钩子将重定向值设置为 true,但是我的 setRedirect 没有更新重定向变量,因此我将永远无法查看 /secret 路由,而是它总是将我重定向到 /login页。
这是我在 React 组件上的代码 /秘密
import { useState, useEffect } from "react";
import { Navigate } from "react-router-dom";
export default function SecretPage() {
const [redirect, setRedirect] = useState(false);
useEffect(() => {
async function authChecker() {
try {
const response = await fetch("http://localhost:4000/authenticate", {
credentials: "include",
});
if (response.ok) {
setRedirect(true); //IT IS NOT UPDATING
} else {
console.error('Authentication failed:', response.statusText);
}
} catch (error) {
console.error('Error checking authentication:', error);
// Handle error
}
}
authChecker();
}, []);
if (!redirect) {
return <Navigate to="/login" state={{ message: "You are not logged in, please login" }} />;
}
return (
<h1>SecretPage</h1>
);
}
这是我在路由 http://localhost:4000/authenticate 上的后端函数
app.get("/authenticate", (req, res) => {
const token = req.cookies.jwt;
if (token) {
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
console.error('Error verifying token:', err);
return res.status(401).json({ message: 'Unauthorized' });
} else {
// Token is valid, allow access to protected resource
return res.status(200).json({ message: 'Access granted' });
}
});
} else {
res.status(401).json({ message: 'Unauthorized' });
}
});
这是因为您重定向变量以 0 开头,您必须了解您的 API 响应不是立即的,但您的渲染会立即响应,从而使您的 if 块立即渲染您的 Redirect 组件。
我建议使用另一个 useState 来解决这个问题:
import { useState, useEffect } from "react";
import { Navigate } from "react-router-dom";
export default function SecretPage() {
const [redirect, setRedirect] = useState(false);
const [done, setDone] = useState(false);
useEffect(() => {
async function authChecker() {
try {
const response = await fetch("http://localhost:4000/authenticate", {
credentials: "include",
});
if (response.ok) {
setRedirect(true); //IT IS NOT UPDATING
} else {
console.error('Authentication failed:', response.statusText);
}
} catch (error) {
console.error('Error checking authentication:', error);
// Handle error
}
setDone(true)
}
authChecker();
}, []);
if (!done) {
return <div>Loading...</div>;
}
if (!redirect) {
return <Navigate to="/login" state={{ message: "You are not logged in, please login" }} />;
}
return (
<h1>SecretPage</h1>
);
}