给你的应用加上Google账号登录

在你的网站上增加一个"使用 Google 账号登录"的按钮,通常涉及到 Google Identity Services (GIS),特别是它的"Sign In with Google"功能。这主要包括前端集成(显示按钮和处理响应)和后端验证(验证 Google 返回的令牌,并创建或登录用户)。

以下是详细的步骤和代码示例:

核心概念

  1. OAuth 2.0 / OpenID Connect (OIDC): Google 登录基于这些标准,允许用户授权第三方应用访问他们的 Google 身份信息,而无需分享密码。
  2. ID Token: Google 登录成功后,你会收到一个 ID Token。这是一个 JSON Web Token (JWT),包含了用户的基本身份信息(如邮箱、姓名、头像等)。这个 Token 需要在你的后端进行验证。
  3. Client ID: 这是你在 Google Cloud Console 中为你的应用创建的唯一标识符。
  4. Redirect URI (授权重定向 URI): Google 认证成功后,会将用户重定向回你网站上的指定 URL。

步骤一:在 Google Cloud Console 设置你的项目

  1. 登录 Google Cloud Console : 访问 console.cloud.google.com
  2. 创建或选择项目 :
    • 如果你还没有项目,点击左上角的"选择项目"下拉菜单,然后点击"新建项目"。
    • 如果你已有项目,选择它。
  3. 启用 API 和服务 :
    • 在左侧导航栏中,点击"API 和服务">"库"。
    • 搜索"Google Identity Platform"并启用它。
  4. 配置 OAuth 同意屏幕 :
    • 在左侧导航栏中,点击"API 和服务">"OAuth 同意屏幕"。
    • 选择用户类型(通常是"外部")。
    • 填写应用名称、用户支持邮箱、开发者联系信息等。
    • 授权范围 (Scopes) : 如果只是登录,通常 email, profile, openid 足够了。
    • 保存并继续。
  5. 创建凭据 :
    • 在左侧导航栏中,点击"API 和服务">"凭据"。
    • 点击"创建凭据">"OAuth 客户端 ID"。
    • 应用类型: 选择"Web 应用"。
    • 名称: 给你的 OAuth 客户端起个名字(例如:"MyWebApp Google Login")。
    • 授权的 JavaScript 来源 (Authorized JavaScript origins) : 这是你的网站运行的域名。例如:http://localhost:3000 (用于本地开发) 或 https://www.yourdomain.com注意:不包含路径,也不带 / 结尾。
    • 授权的重定向 URI (Authorized redirect URIs) : 这是 Google 认证成功后将 ID Token 或授权码发送到的你的后端端点。例如:http://localhost:3000/api/auth/google/callbackhttps://www.yourdomain.com/api/auth/google/callback
    • 点击"创建"。
    • 你会得到一个 客户端 ID (Client ID)客户端秘钥 (Client Secret) 。请记下它们。客户端秘钥是敏感信息,绝不能暴露在前端代码中!

步骤二:前端集成 (HTML & JavaScript)

在你的网站页面中,你需要引入 Google 的 JavaScript 库,并渲染登录按钮。

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>使用 Google 登录</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            margin: 0;
            background-color: #f0f2f5;
        }
        .login-container {
            background-color: #fff;
            padding: 40px;
            border-radius: 8px;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
            text-align: center;
        }
        h1 {
            color: #333;
            margin-bottom: 30px;
        }
        #g_id_onload {
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <div class="login-container">
        <h1>欢迎登录</h1>

        <!-- 这是 Google Identity Services 的加载器,它会处理初始化和显示按钮 -->
        <!-- data-client_id 替换成你在 Google Cloud Console 中获得的客户端 ID -->
        <!-- data-callback 是登录成功后调用的 JavaScript 函数名 -->
        <div id="g_id_onload"
             data-client_id="YOUR_GOOGLE_CLIENT_ID"
             data-context="signin"
             data-ux_mode="popup" <!-- "popup" 或 "redirect" -->
             data-login_uri="YOUR_AUTHORIZED_REDIRECT_URI_FOR_BACKEND" <!-- 如果 ux_mode 是 redirect,需要这个 -->
             data-callback="handleCredentialResponse"
             data-auto_prompt="false"> <!-- 是否自动弹出,一般设置为 false -->
        </div>

        <!-- 这是 Google 登录按钮的容器 -->
        <!-- 它会自动被 Google 的 JS 替换为一个漂亮的登录按钮 -->
        <div class="g_id_signin"
             data-type="standard"        <!-- "standard" 或 "icon" -->
             data-size="large"           <!-- "small", "medium", "large" -->
             data-theme="outline"        <!-- "outline" 或 "filled_blue", "filled_black" -->
             data-text="signin_with"     <!-- "signin_with", "continue_with", "signup_with" -->
             data-shape="rectangular"    <!-- "rectangular" 或 "pill" -->
             data-logo_alignment="left"> <!-- "left" 或 "center" -->
        </div>
    </div>

    <!-- 引入 Google Identity Services 库 -->
    <script src="https://accounts.google.com/gsi/client" async defer></script>

    <script>
        // 登录成功后的回调函数
        function handleCredentialResponse(response) {
            console.log("Encoded ID Token: " + response.credential);

            // 将 ID Token 发送到你的后端进行验证
            fetch('/api/auth/google', { // 替换成你的后端认证端点
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ token: response.credential }),
            })
            .then(res => res.json())
            .then(data => {
                if (data.success) {
                    console.log('登录成功:', data.user);
                    // 登录成功后,可以重定向用户或更新UI
                    window.location.href = '/dashboard'; // 示例:跳转到仪表盘页面
                } else {
                    console.error('登录失败:', data.message);
                    alert('登录失败: ' + data.message);
                }
            })
            .catch(error => {
                console.error('发送 ID Token 到后端时出错:', error);
                alert('登录过程中发生错误。');
            });
        }
    </script>
</body>
</html>

重要提示:

  • YOUR_GOOGLE_CLIENT_ID 替换为你在 Google Cloud Console 中获得的客户端 ID。
  • YOUR_AUTHORIZED_REDIRECT_URI_FOR_BACKEND 应该与你在 Google Cloud Console 中配置的授权重定向 URI 之一匹配,这个 URI 会被用来接收 Google 返回的数据(虽然对于 popup 模式,前端 JS 已经拿到 Token,但最好也配置好)。
  • fetch('/api/auth/google', ...) 中的 URL 应该指向你自己的后端 API 端点,负责接收和验证 Google ID Token。
  • data-ux_mode:
    • popup:会在当前页面弹出 Google 认证窗口。
    • redirect:会将用户重定向到 Google 认证页面,成功后重定向回你的 data-login_uripopup 通常更流畅。

步骤三:后端验证 (示例:Node.js with Express)

后端的主要任务是接收前端发来的 ID Token,验证它的真实性,然后从 Token 中提取用户信息,并根据这些信息在你的数据库中查找或创建用户,最后创建会话。

这里以 Node.js (Express) 为例,其他后端语言(Python, Java, PHP 等)也有类似的 Google 认证库。

1. 安装依赖:

bash 复制代码
npm install express google-auth-library jsonwebtoken

2. 后端代码示例 (server.js 或类似文件):

javascript 复制代码
const express = require('express');
const { OAuth2Client } = require('google-auth-library');
const jwt = require('jsonwebtoken'); // 用于生成你自己的会话 token 或其他用途

const app = express();
const port = 3000;

// 配置
const GOOGLE_CLIENT_ID = 'YOUR_GOOGLE_CLIENT_ID'; // 替换成你的客户端 ID
const GOOGLE_CLIENT_SECRET = 'YOUR_GOOGLE_CLIENT_SECRET'; // 替换成你的客户端秘钥
const JWT_SECRET = 'YOUR_SUPER_SECRET_KEY'; // 用于签发你自己的 JWT,请务必使用强随机字符串

// Google OAuth 客户端
const client = new OAuth2Client(GOOGLE_CLIENT_ID);

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

// CORS 配置 (仅用于开发环境,生产环境请根据实际情况配置)
app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // 允许你的前端域名
    res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    if (req.method === 'OPTIONS') {
        return res.sendStatus(200);
    }
    next();
});


// 处理 Google 登录的回调
app.post('/api/auth/google', async (req, res) => {
    const { token } = req.body;

    if (!token) {
        return res.status(400).json({ success: false, message: 'No ID token provided' });
    }

    try {
        // 1. 验证 ID Token
        const ticket = await client.verifyIdToken({
            idToken: token,
            audience: GOOGLE_CLIENT_ID, // 确保这个 token 是为你的应用签发的
        });

        // 获取用户 payload
        const payload = ticket.getPayload();
        // console.log('Google Payload:', payload);

        const userId = payload['sub']; // Google 用户的唯一 ID
        const email = payload['email'];
        const name = payload['name'];
        const picture = payload['picture'];
        const email_verified = payload['email_verified'];

        if (!email_verified) {
            return res.status(401).json({ success: false, message: 'Google email not verified.' });
        }

        // 2. 在你的数据库中查找或创建用户
        // 这是一个示例,你需要根据你的数据库和用户模型来替换这部分逻辑
        let user = await findUserByEmail(email); // 假设你有一个函数来查找用户

        if (!user) {
            // 用户不存在,创建新用户
            user = await createUser({
                googleId: userId,
                email: email,
                name: name,
                profilePicture: picture,
                // 其他你想要存储的用户信息
            });
            console.log('新用户创建:', user);
        } else {
            // 用户存在,更新其 Google ID 或其他信息 (可选)
            if (!user.googleId) {
                await updateUserGoogleId(user.id, userId); // 假设你有一个函数更新 Google ID
            }
            console.log('用户已存在,登录成功:', user);
        }

        // 3. 生成会话(例如,使用 JWT)
        const sessionToken = jwt.sign(
            { id: user.id, email: user.email, googleId: user.googleId },
            JWT_SECRET,
            { expiresIn: '1h' } // 会话有效期
        );

        // 4. 返回成功响应和会话 token
        res.status(200).json({
            success: true,
            message: '登录成功',
            token: sessionToken, // 返回会话 token 给前端
            user: { id: user.id, email: user.email, name: user.name, picture: user.profilePicture } // 返回部分用户信息
        });

    } catch (error) {
        console.error('Google 认证失败:', error);
        res.status(401).json({ success: false, message: 'Google 认证失败,请重试。' });
    }
});

// 示例:数据库操作函数 (你需要替换为真实数据库操作)
async function findUserByEmail(email) {
    // 模拟从数据库查找用户
    console.log(`查询用户: ${email}`);
    // 假设你的数据库中有一个用户集合/表
    // return db.users.findOne({ email });
    // 为演示目的,我们模拟一个用户
    if (email === 'test@example.com') {
        return { id: '123', email: 'test@example.com', name: 'Test User', googleId: 'someGoogleId' };
    }
    return null;
}

async function createUser(userData) {
    // 模拟在数据库中创建新用户
    console.log('创建新用户:', userData);
    // return db.users.insertOne(userData);
    // 为演示目的,返回一个模拟的新用户对象
    return { id: Math.random().toString(36).substr(2, 9), ...userData };
}

async function updateUserGoogleId(userId, googleId) {
    // 模拟更新用户的 Google ID
    console.log(`更新用户 ${userId} 的 Google ID 为 ${googleId}`);
    // return db.users.updateOne({ id: userId }, { $set: { googleId: googleId } });
}


app.listen(port, () => {
    console.log(`后端服务器运行在 http://localhost:${port}`);
    console.log(`请确保你的前端在 http://localhost:3000 运行以进行测试。`);
});

注意事项:

  • YOUR_GOOGLE_CLIENT_IDYOUR_GOOGLE_CLIENT_SECRET 替换为你在 Google Cloud Console 中获得的真实值。
  • JWT_SECRET 应该是一个非常长且随机的字符串,用于签名你的会话 JWT。
  • findUserByEmail, createUser, updateUserGoogleId 只是占位函数,你需要根据你实际使用的数据库(如 MongoDB, PostgreSQL, MySQL 等)和 ORM/库(如 Mongoose, Sequelize, TypeORM 等)来实现它们。
  • 安全性 : GOOGLE_CLIENT_SECRET 绝对不能暴露在前端。它只在后端使用。ID Token 验证时,实际上只需要 GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRET 主要用于授权码流程(如果你需要访问其他 Google API)或刷新令牌。
  • HTTPS: 在生产环境中,你的网站必须使用 HTTPS。Google 不允许在非 HTTPS 的环境中进行 OAuth 认证。
  • 会话管理: 后端成功验证并登录用户后,通常会创建并返回一个会话令牌(如 JWT)或设置一个 HTTP cookie。前端在后续请求中携带这个令牌/cookie,以保持用户登录状态。

总结流程:

  1. Google Cloud Console : 创建项目,配置 OAuth 同意屏幕,获取 Client IDClient Secret,设置正确的 Authorized JavaScript originsAuthorized redirect URIs
  2. 前端 :
    • 引入 Google Identity Services JS 库。
    • 使用 g_id_onload 初始化 Google 登录,传入你的 Client ID 和一个回调函数名。
    • 使用 g_id_signin 容器自动渲染 Google 登录按钮。
    • 在回调函数 handleCredentialResponse 中,获取 ID Token
    • ID Token 通过 AJAX (fetch) 发送到你的后端 API。
  3. 后端 :
    • 接收前端发送的 ID Token
    • 使用 Google 提供的库(如 google-auth-library)验证 ID Token 的真实性。
    • 从验证后的 ID Token 中提取用户数据(邮箱、姓名等)。
    • 根据邮箱在你的数据库中查找用户。
      • 如果用户不存在,则创建新用户记录。
      • 如果用户存在,则更新其信息(可选)。
    • 为用户创建你自己的会话(例如,生成一个 JWT 并返回给前端)。
    • 前端收到会话令牌后,可以在后续请求中带上它来保持登录状态。

这是一个完整的集成指南,可以帮助你在网站上实现 Google 登录功能。

相关推荐
鹏北海4 分钟前
微前端实现方式:HTML Entry 与 JS Entry 的区别
前端·javascript·面试
爱上妖精的尾巴10 分钟前
6-5 WPS JS宏 集合成员迭代(随机生成试题)
开发语言·前端·javascript
是你的小橘呀10 分钟前
React 组件通信:组件间的 "悄悄话" 指南
前端·javascript
糖墨夕26 分钟前
超越随机:JavaScript中真正可靠的唯一标识符生成策略
前端·javascript
码界奇点26 分钟前
基于SpringBoot3+Vue的前后端分离电商系统设计与实现
前端·javascript·vue.js·spring·毕业设计·鸿蒙系统·源代码管理
m0_4711996336 分钟前
【vue】通俗易懂的剖析vue3的响应式原理
前端·javascript·vue.js
哟哟耶耶1 小时前
css-Echarts图表tooltip / label文本过长 超出屏幕边缘或容器范围
前端·javascript·echarts
郑州光合科技余经理1 小时前
解决方案:全球化时代下的海外版外卖系统
大数据·开发语言·前端·javascript·人工智能·架构·php
smileNicky1 小时前
分组拖动排序功能全流程实现(前端Sortable.js + 后端Java批量更新)
java·前端·javascript
一路向前的月光1 小时前
Eltable二次封装
javascript·vue.js·elementui