如何在React中通过fetch API存储Express服务器发送的JWT Cookie?
我用React、Express和MongoDB开发注册表单,已实现POST请求并将用户数据存入数据库,但数据保存后,无法通过res.cookie('jwt',token)在浏览器中存储JWT令牌。
React表单代码
type Props = { children: React.ReactNode; }; export const SignupLayout = ({ children }: Props) => { const user = { email: 'alexy@gmail.com', username: 'alexladies', password: 'pasrfsfsdfgfdsd', securityQuestion: "father's name", securityAnswer: 'jhon', joinedDate: '12-12-2023', }; const handleSignup = async (event: React.SyntheticEvent) => { event.preventDefault(); // 问题出在这里 await fetch('http://localhost:3000/signup', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(user), }) .then((reponse) => reponse.json()) .then((json) => console.log(json)) .catch((err) => console.log(err)); }; return ( <form onSubmit={handleSignup} method='post' action='/signup' className='sm:px-20 md:w-2/3 md:px-12 lg:w-1/2 lg:px-4 lg:my-4 xl:mt-16 xl:w-1/3 xl:px-16 mx-auto bg-white rounded-2xl py-10 text-center ' > {children} </form> ); };
Express服务器代码
const User = require('../../models/user'); const { handleError } = require('./error'); const { createToken } = require('../utils/token'); const getSignup = (req, res) => { // 该接口可成功在浏览器存储Cookie res.cookie('name', 'value'); res.send('ok'); }; const postSignup = async (req, res) => { // 该接口无法在浏览器存储Cookie! const { email, password, username, securityQuestion, securityAnswer, joinedDate, } = req.body; const user = new User({ email, password, username, securityQuestion, securityAnswer, joinedDate, }); await user .save() .then(() => res.cookie('jwt', createToken(user._id))) .then(() => res.status(200).json(user._id)) .catch((err) => { res.status(400).json(handleError(err)); }); }; module.exports = { getSignup, postSignup };
我尝试在fetch请求中添加credentials:'include',但未生效。
截图

解决方法
配置CORS允许凭证
Express需安装并配置cors包,指定允许的源(不能用*,否则浏览器会拒绝携带Cookie):const cors = require('cors'); app.use(cors({ origin: 'http://localhost:你的React端口', // 例如React运行在3001则填此地址 credentials: true }));修正Fetch的凭证配置
确保credentials属性与method、headers同级,正确配置:await fetch('http://localhost:3000/signup', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify(user), })完善Cookie属性设置
给res.cookie添加必要属性,确保Cookie能被浏览器正确存储:res.cookie('jwt', createToken(user._id), { httpOnly: true, // 防XSS攻击,建议添加 secure: process.env.NODE_ENV === 'production', // 生产环境启用(需HTTPS) sameSite: 'lax', // 或根据需求设为'none'(需配合secure=true) maxAge: 24 * 60 * 60 * 1000 // 设置Cookie过期时间,例如1天 });优化Promise链逻辑
res.cookie是同步操作,无需用then链式调用,改用更清晰的async/await写法:try { const savedUser = await user.save(); res.cookie('jwt', createToken(savedUser._id), /* 上述Cookie属性 */); res.status(200).json(savedUser._id); } catch (err) { res.status(400).json(handleError(err)); }
内容的提问来源于stack exchange,提问作者Ala Eddine Menai
相关产品推荐
相关产品推荐

