在你的网站上增加一个"使用 Google 账号登录"的按钮,通常涉及到 Google Identity Services (GIS),特别是它的"Sign In with Google"功能。这主要包括前端集成(显示按钮和处理响应)和后端验证(验证 Google 返回的令牌,并创建或登录用户)。
以下是详细的步骤和代码示例:
核心概念
- OAuth 2.0 / OpenID Connect (OIDC): Google 登录基于这些标准,允许用户授权第三方应用访问他们的 Google 身份信息,而无需分享密码。
- ID Token: Google 登录成功后,你会收到一个 ID Token。这是一个 JSON Web Token (JWT),包含了用户的基本身份信息(如邮箱、姓名、头像等)。这个 Token 需要在你的后端进行验证。
- Client ID: 这是你在 Google Cloud Console 中为你的应用创建的唯一标识符。
- Redirect URI (授权重定向 URI): Google 认证成功后,会将用户重定向回你网站上的指定 URL。
步骤一:在 Google Cloud Console 设置你的项目
- 登录 Google Cloud Console : 访问 console.cloud.google.com。
- 创建或选择项目 :
- 如果你还没有项目,点击左上角的"选择项目"下拉菜单,然后点击"新建项目"。
- 如果你已有项目,选择它。
- 启用 API 和服务 :
- 在左侧导航栏中,点击"API 和服务">"库"。
- 搜索"Google Identity Platform"并启用它。
- 配置 OAuth 同意屏幕 :
- 在左侧导航栏中,点击"API 和服务">"OAuth 同意屏幕"。
- 选择用户类型(通常是"外部")。
- 填写应用名称、用户支持邮箱、开发者联系信息等。
- 授权范围 (Scopes) : 如果只是登录,通常
email,profile,openid足够了。 - 保存并继续。
- 创建凭据 :
- 在左侧导航栏中,点击"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/callback或https://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_uri。popup通常更流畅。
步骤三:后端验证 (示例: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_ID和YOUR_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_ID。GOOGLE_CLIENT_SECRET主要用于授权码流程(如果你需要访问其他 Google API)或刷新令牌。 - HTTPS: 在生产环境中,你的网站必须使用 HTTPS。Google 不允许在非 HTTPS 的环境中进行 OAuth 认证。
- 会话管理: 后端成功验证并登录用户后,通常会创建并返回一个会话令牌(如 JWT)或设置一个 HTTP cookie。前端在后续请求中携带这个令牌/cookie,以保持用户登录状态。
总结流程:
- Google Cloud Console : 创建项目,配置 OAuth 同意屏幕,获取
Client ID和Client Secret,设置正确的Authorized JavaScript origins和Authorized redirect URIs。 - 前端 :
- 引入 Google Identity Services JS 库。
- 使用
g_id_onload初始化 Google 登录,传入你的Client ID和一个回调函数名。 - 使用
g_id_signin容器自动渲染 Google 登录按钮。 - 在回调函数
handleCredentialResponse中,获取ID Token。 - 将
ID Token通过 AJAX (fetch) 发送到你的后端 API。
- 后端 :
- 接收前端发送的
ID Token。 - 使用 Google 提供的库(如
google-auth-library)验证ID Token的真实性。 - 从验证后的
ID Token中提取用户数据(邮箱、姓名等)。 - 根据邮箱在你的数据库中查找用户。
- 如果用户不存在,则创建新用户记录。
- 如果用户存在,则更新其信息(可选)。
- 为用户创建你自己的会话(例如,生成一个 JWT 并返回给前端)。
- 前端收到会话令牌后,可以在后续请求中带上它来保持登录状态。
- 接收前端发送的
这是一个完整的集成指南,可以帮助你在网站上实现 Google 登录功能。