我正在尝试使用 JWT 令牌和仅 HTTP cookie 与 Express.js 为管理面板创建身份验证。当我从前端发送请求时,它给出了成功的响应,但不返回任何 cookie。但是,当我尝试来自 Postman 的相同请求时,它会按预期返回 cookie。
const handleSubmit = async (e) => {
e.preventDefault();
if (loading) return;
setLoading(true); // Start loading
try {
const response = await axios.post(
`${import.meta.env.VITE_BACKEND_URI}/adminLogin`,
{ Id: id, Password: password }
);
if (response.status === 200) {
navigate('/Home');
}
} catch (error) {
setError(error.response?.data?.error || "Login failed. Please check your internet or try again later.");
} finally {setLoading(false);}
};
点击提交按钮后,我被重定向到/Home路线。
下面是我创建和发送 cookie 的 api 端点
import express from 'express';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
dotenv.config();
const router = express.Router();
router.post('/', (req, res) => {
try {
const { Id, Password } = req.body;
console.log(process.env.ADMIN_ID === String(Id));
console.log(process.env.ADMIN_PASSWORD === String(Password));
if (process.env.ADMIN_ID === String(Id) && process.env.ADMIN_PASSWORD === String(Password)) {
const token = jwt.sign({ id: Id, password: Password }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.cookie("jwtToken", token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: "Lax",
maxAge: 3600 * 1000,
path: '/',
});
console.log("correct");
res.sendStatus(200);
} else {
res.status(401).json({ error: "invalid credentials" });
}
} catch (error) {
console.log(error);
res.status(500).json({ error: "Internal Server Error" });
}
});
export default router;
这是我的 server.js 文件,我认为它包含所有必需的中间件,如果我缺少任何中间件,请告诉我
import express from "express";
import bodyParser from "body-parser";
import cookieParser from 'cookie-parser';
import cors from "cors";
import dotenv from "dotenv";
import connectDB from "./config/db.js";
import loginRoute from "./routes/Login.js";
import signUpRoute from "./routes/SignUp.js";
import authorizationRoute from "./routes/Authorize.js";
import deleteUserRoute from "./routes/deleteUser.js";
import sendEmailRoute from "./routes/Subscriber.js";
import sendInquiriesRoute from "./routes/Inquiries.js";
import adminLoginRoute from "./routes/AdminLogin.js";
import tokenRoute from "./middleware/auth.js";
dotenv.config();
connectDB();
const server = express();
const port = process.env.PORT_NO || 3000;
server.use(bodyParser.json());
server.use(cookieParser());
server.use(cors({
origin: ["http://localhost:4000", "http://localhost:5173"],
credentials: true,
}));
// Home route
server.get('/', (req, res) => {
res.send("this is home route");
});
// Use the routes
server.use('/login', loginRoute);
server.use('/signUp', signUpRoute);
server.use('/authorizeEmail', authorizationRoute);
server.use('/deleteUser', deleteUserRoute);
server.use('/sendEmail', sendEmailRoute);
server.use('/sendInquiries', sendInquiriesRoute);
server.use('/adminLogin', adminLoginRoute);
server.use("/checkToken", tokenRoute);
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
此外,如果我将后续请求发送到以下端点
import express from 'express';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
dotenv.config();
const router = express.Router();
router.get('/', (req, res) => {
const token = req.cookies.jwtToken;
console.log(token)
if (!token) {
return res.status(401).json({ error: "Authentication token missing" });
}
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
return res.status(403).json({ error: "Invalid or expired token" });
}
return res.sendStatus(200)
});
});
导出默认路由器;
我在控制台中收到“身份验证令牌丢失”
在 Axios 请求中添加
withCredentials: true
,以确保跨域请求发送 cookie。
像这样更新你的前端代码:
const handleSubmit = async (e) => {
e.preventDefault();
if (loading) return;
setLoading(true); // Start loading
try {
const response = await axios.post(
`${import.meta.env.VITE_BACKEND_URI}/adminLogin`,
{ Id: id, Password: password },
{ withCredentials: true } // Ensures cookies are sent with the request
);
if (response.status === 200) {
navigate('/Home');
}
} catch (error) {
setError(error.response?.data?.error || "Login failed. Please check your internet or try again later.");
} finally {
setLoading(false);
}
};