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

MERN应用中Passport-Google-OAuth+JWT认证:前端数据获取问题

解决React前端获取OAuth+JWT认证数据的问题

先给你捋清楚当前代码里的关键问题,再一步步给出修改方案:

1. 后端token生成中间件写错了

你现在的generateAccessToken是普通函数,但passport后续需要的是Express中间件,得能拿到请求对象里的用户信息,还要把生成的token挂载到请求对象上供后续路由使用。修改token.js:

exports.generateAccessToken = (req, res, next) => {
  // 从passport处理后的req.user中获取用户ID
  const token = jwt.sign({ _id: req.user._id }, process.env.JWT_SECRET, {
    expiresIn: "1h",
    issuer: process.env.JWT_ISSUER,
  });
  req.token = token; // 将token挂载到req对象
  next(); // 执行下一个中间件/路由处理函数
};

2. 后端callback路由不能直接返回JSON

用户跳转到谷歌认证后,谷歌会回调你的/auth/google/callback接口,如果直接返回JSON,浏览器会显示纯JSON文本,无法回到React应用。正确做法是重定向回前端页面,把token和邮箱作为URL参数传递。修改server.js里的callback路由:

app.get(
  "/auth/google/callback",
  passport.authenticate("google", { session: false }),
  generateAccessToken,
  function (req, res) {
    if (req.token) {
      const email = req.user.email;
      const token = req.token;
      // 重定向到前端登录成功页面,用encodeURIComponent处理特殊字符
      return res.redirect(`http://localhost:3000/login-success?email=${encodeURIComponent(email)}&token=${token}`);
    } else {
      // 认证失败时重定向到错误页
      res.redirect(`http://localhost:3000/login-error?message=Something went wrong`);
    }
  }
);

3. 前端登录逻辑需调整

你之前写的useLogin直接调用/auth/google/callback是无效的,这个接口是谷歌专属回调地址,不能直接请求。前端只需要做两件事:

  • 提供登录按钮,引导用户跳转到后端的谷歌认证入口
  • 写一个登录成功页面,解析URL参数并保存用户数据

登录按钮组件

const Login = () => {
  const handleGoogleLogin = () => {
    // 直接跳转到后端的谷歌认证接口
    window.location.href = "http://localhost:4000/auth/google";
  };

  return <button onClick={handleGoogleLogin}>用谷歌账号登录</button>;
};

export default Login;

登录成功页面(LoginSuccess.js)

import { useEffect } from "react";
import { useAuthContext } from "../contexts/AuthContext";

const LoginSuccess = () => {
  const { dispatch } = useAuthContext;

  useEffect(() => {
    // 解析URL中的查询参数
    const urlParams = new URLSearchParams(window.location.search);
    const email = urlParams.get("email");
    const token = urlParams.get("token");

    if (email && token) {
      // 将用户数据存入localStorage并更新全局状态
      const userData = { email, token };
      localStorage.setItem("user", JSON.stringify(userData));
      dispatch({ type: "LOGIN", payload: userData });
      // 跳转到首页或其他需要登录的页面
      window.location.href = "/";
    } else {
      // 无有效参数时跳回登录页
      window.location.href = "/login";
    }
  }, [dispatch]);

  return <div>登录成功,正在跳转...</div>;
};

export default LoginSuccess;

4. 配置跨域支持

后端需要安装并配置cors包,允许前端域名的跨域请求:

npm install cors

在server.js中添加配置:

const cors = require("cors");
// 允许前端localhost:3000的跨域请求
app.use(cors({
  origin: "http://localhost:3000",
  credentials: true
}));

完整流程梳理

  1. 用户点击前端的谷歌登录按钮,跳转到后端/auth/google接口
  2. 后端重定向到谷歌官方认证页面,用户完成账号授权
  3. 谷歌认证通过后,自动重定向到后端/auth/google/callback接口
  4. 后端通过passport验证用户信息,生成JWT,再重定向回前端login-success页面并携带参数
  5. 前端解析URL参数,保存用户数据到localStorage并更新全局状态,最后跳转到首页

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:27:39