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

Google登录无法连接后端服务器问题求助

如何在Express服务器中接收Google登录的用户个人资料?

问题背景

首次实现Google登录功能:前端基于React 16使用@dump-work/react-google-login库,后端采用Passport结合Google OAuth2。目前Google弹窗可正常打开并选择账号,弹窗关闭后服务器端无任何响应,需解决如何在Express服务器接收用户Google个人资料的问题。

前端代码

import "./App.css";
import { GoogleLogin } from 'react-google-login';

function App() {
  const responseGoogle = (response) => {
    // Handle the Google login response here
    console.log(response);
  };
  return (
    <div className="App">
       <GoogleLogin
        clientId="882516377786-e6dfholj9nsma16kravu3k5v103q6lqp.apps.googleusercontent.com"
        buttonText="Login with Google"
        onSuccess={responseGoogle}
        onFailure={responseGoogle}
        cookiePolicy={'single_host_origin'}
      />
    </div>
  );
}

export default App;

后端代码

const express = require("express");
const app = express();
const port = 5000;
const cors = require("cors");
const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20").Strategy;

app.use(cors());
app.use(passport.initialize());

passport.use(
  new GoogleStrategy(
    {
      clientID: "myClientId",
      clientSecret: "mySecret",
      callbackURL: "http://localhost:5000/auth/google/callback",
    },
    function (accessToken, refreshToken, profile, cb) {
      // Implement your logic here to handle the authenticated user's data
      console.log("Google Profile:", profile);
      return cb(null, profile);
    }
  )
);

app.get(
  "/auth/google",
  passport.authenticate("google", {
    scope: ["profile", "email"],
  })
);

app.get(
  "/auth/google/callback",
  passport.authenticate("google", { failureRedirect: "/login" }),
  function (req, res) {
    console.log("Authentication success");
    res.redirect("/"); // Redirect to the home page or wherever you want
  }
);

app.get("/", (req, res) => res.send("Hello World!"));

// Error handler for unhandled errors
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send("Something went wrong!");
});

// Start the server
app.listen(port, () => console.log(`App listening on port ${port}!`));

问题核心

前端采用客户端侧OAuth流(隐式授权/ID Token模式),弹窗回调直接在前端处理(redirect_uri为storagerelay://http/localhost:5173),完全没有将授权凭证发送到后端;而后端配置的是服务器侧OAuth流(授权码模式),等待前端跳转触发授权请求,两者模式不匹配导致后端收不到任何请求。

解决方案

提供两种适配方案,按需选择:

方案一:改用服务器侧授权码流(推荐,安全性更高)

1. 前端修改

替换GoogleLogin组件为普通跳转按钮,直接引导用户访问后端的授权路由:

import "./App.css";

function App() {
  return (
    <div className="App">
      <a href="http://localhost:5000/auth/google" className="google-login-btn">
        Login with Google
      </a>
    </div>
  );
}

export default App;

2. 后端调整

  • 确保代码中clientID、clientSecret替换为Google控制台的实际值
  • 确认Google控制台的OAuth 2.0客户端ID中,已添加回调URL:http://localhost:5000/auth/google/callback

3. 可选:添加会话支持(保持登录状态)

若需持久化用户登录状态,添加express-session及Passport序列化逻辑:

const session = require('express-session');

// 在passport.initialize()之前添加会话中间件
app.use(session({
  secret: 'your-custom-secret-key',
  resave: false,
  saveUninitialized: false
}));
app.use(passport.session());

// Passport序列化/反序列化用户(示例,可根据数据库逻辑调整)
passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  // 此处可从数据库查询用户信息,示例直接返回
  done(null, { id });
});

方案二:前端传ID Token到后端验证(客户端侧流适配)

1. 前端修改

在登录回调中,将Google返回的idToken发送到后端验证接口:

const responseGoogle = async (response) => {
  console.log(response);
  if (response.tokenId) {
    try {
      const res = await fetch('http://localhost:5000/auth/google/verify-token', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ idToken: response.tokenId })
      });
      const data = await res.json();
      console.log('后端验证后的用户信息:', data);
    } catch (err) {
      console.error('发送token失败:', err);
    }
  }
};

2. 后端新增验证接口

使用Google官方库验证ID Token的合法性:

const { OAuth2Client } = require('google-auth-library');
const client = new OAuth2Client('你的clientID'); // 与前端clientID保持一致

app.use(express.json()); // 解析JSON请求体

app.post('/auth/google/verify-token', async (req, res) => {
  const { idToken } = req.body;
  try {
    const ticket = await client.verifyIdToken({
      idToken: idToken,
      audience: '你的clientID', // 必须匹配前端的clientID
    });
    const payload = ticket.getPayload();
    console.log('Google用户资料:', payload);
    res.json({ user: payload });
  } catch (err) {
    console.error('验证token失败:', err);
    res.status(401).send('无效的token');
  }
});

3. 控制台配置

确保Google控制台的OAuth 2.0客户端ID中,已添加前端地址作为授权来源:http://localhost:5173

额外检查项

  • 若应用处于测试状态,需在Google控制台的OAuth同意屏幕中添加测试用户
  • 确认客户端ID、密钥前后端一致,无拼写错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 12:17:33