You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用React和Node.js实现Http-only Cookie-JWT认证?

一、React端用户认证流程实现

Http-only Cookie由浏览器自动管理,React端不用手动存储token,核心处理好请求的Cookie携带、前端状态同步和受保护路由即可:

1. 登录请求处理

登录时直接调用后端登录接口,关键要在请求里加credentials: 'include',让浏览器自动保存并携带Cookie(跨域场景必须加,同源场景也建议加上):

// React登录组件示例
const Login = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const { setUser } = useAuth(); // 假设用全局Context管理用户状态
  const navigate = useNavigate();

  const handleLogin = async (e) => {
    e.preventDefault();
    try {
      const res = await fetch('http://localhost:5000/api/login', {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username, password })
      });
      const data = await res.json();
      if (res.ok) {
        // 登录成功,把后端返回的用户信息存入前端状态
        setUser(data.user);
        navigate('/dashboard');
      } else {
        alert(data.message || '登录失败');
      }
    } catch (err) {
      console.error('登录请求出错:', err);
      alert('网络异常,请稍后重试');
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="用户名"
        required
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="密码"
        required
      />
      <button type="submit">登录</button>
    </form>
  );
};

2. 页面刷新时恢复登录状态

页面刷新后前端状态会丢失,需要调用后端的验证接口,通过Cookie中的JWT获取当前用户信息,恢复前端状态:

// 全局状态初始化(比如在App.js或AuthContext中)
useEffect(() => {
  const checkAuthStatus = async () => {
    try {
      const res = await fetch('http://localhost:5000/api/verify', {
        credentials: 'include'
      });
      if (res.ok) {
        const user = await res.json();
        setUser(user);
      } else {
        // 未登录或token过期,清空前端状态
        setUser(null);
      }
    } catch (err) {
      console.error('认证状态检查失败:', err);
      setUser(null);
    }
  };
  checkAuthStatus();
}, []);

3. 实现受保护路由

用React Router包裹需要登录才能访问的页面,判断前端用户状态是否存在:

// 受保护路由组件
const ProtectedRoute = ({ children }) => {
  const { user } = useAuth();
  return user ? children : <Navigate to="/login" />;
};

// 在路由配置中使用
<Routes>
  <Route path="/login" element={<Login />} />
  <Route path="/dashboard" element={
    <ProtectedRoute>
      <Dashboard />
    </ProtectedRoute>
  } />
  <Route path="/profile" element={
    <ProtectedRoute>
      <UserProfile />
    </ProtectedRoute>
  } />
</Routes>

二、Express端JWT验证中间件复用

完全可以沿用你之前EJS项目的验证中间件逻辑,只需要调整几个细节:

1. 核心验证逻辑不变

中间件从Cookie中取出JWT,验证有效性后把用户信息挂载到req.user上,示例:

// Express JWT验证中间件
const jwt = require('jsonwebtoken');

const authenticateToken = (req, res, next) => {
  // 从Cookie中获取token(对应你登录时设置的Cookie名)
  const token = req.cookies.jwt;
  if (!token) {
    return res.sendStatus(401); // 未携带token,返回未授权
  }

  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) {
      return res.sendStatus(403); // token无效或过期,返回禁止访问
    }
    req.user = user;
    next(); // 验证通过,继续执行后续路由
  });
};

2. 挂载到需要认证的路由

把中间件加到需要登录才能访问的路由上,比如验证接口和业务接口:

// 验证用户状态的接口,给React端恢复状态用
app.get('/api/verify', authenticateToken, (req, res) => {
  // 返回用户信息(注意不要返回敏感数据)
  res.json({
    id: req.user.id,
    username: req.user.username,
    role: req.user.role
  });
});

// 受保护的业务接口示例
app.get('/api/dashboard/data', authenticateToken, (req, res) => {
  // 根据req.user获取对应的数据
  res.json({ data: '仅登录用户可见的数据' });
});

3. 跨域与Cookie配置注意

如果React和Express跨域部署,必须配置CORS允许携带Cookie:

const cors = require('cors');
app.use(cors({
  origin: 'http://localhost:3000', // 你的React项目域名/端口
  credentials: true // 允许请求携带Cookie
}));

同时登录时设置Cookie的属性,确保安全且兼容:

// 登录控制器中设置Cookie的代码
res.cookie('jwt', generatedToken, {
  httpOnly: true, // 禁止JS读取,防XSS
  maxAge: 24 * 60 * 60 * 1000, // 1天过期
  sameSite: process.env.NODE_ENV === 'production' ? 'strict' : 'lax', // 生产环境用strict更安全
  secure: process.env.NODE_ENV === 'production' // 生产环境开启,仅HTTPS传输
});

内容的提问来源于stack exchange,提问作者Emiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 18:25:23