Google 登录
Google 登录 提供了一种安全且便捷的方式,让用户使用他们的 Google 账号通过 One Tap、个性化按钮及自动登录进入您的应用。
Nuxt Scripts 提供了一个注册脚本组合式函数 useScriptGoogleSignIn,可让您轻松地在 Nuxt 应用中集成 Google 登录,并实现最佳性能。
实时演示
Sign in with your Google account:
Or
性能优化
该脚本以 async 和 defer 属性加载,避免阻塞渲染,确保核心网页指标(Core Web Vitals)达到最佳。初始化会延迟到您显式调用 initialize() 时执行,赋予您完全控制 One Tap 出现时机的能力。
Nuxt 配置设置
在 Nuxt 应用中全局加载 Google 登录的最简单方法是使用 Nuxt 配置。或者您也可以直接使用 useScriptGoogleSignIn 组合式函数。
export default defineNuxtConfig({
scripts: {
registry: {
googleSignIn: {
clientId: 'YOUR_GOOGLE_CLIENT_ID'
}
}
}
})
export default defineNuxtConfig({
$production: {
scripts: {
registry: {
googleSignIn: {
clientId: 'YOUR_GOOGLE_CLIENT_ID'
}
}
}
}
})
使用环境变量配置
export default defineNuxtConfig({
scripts: {
registry: {
googleSignIn: true,
}
},
runtimeConfig: {
public: {
scripts: {
googleSignIn: {
clientId: '', // NUXT_PUBLIC_SCRIPTS_GOOGLE_SIGN_IN_CLIENT_ID
},
},
},
},
})
useScriptGoogleSignIn
useScriptGoogleSignIn 组合函数让您可以细粒度控制何时以及如何加载 Google 登录。
const { onLoaded } = useScriptGoogleSignIn({
clientId: 'YOUR_GOOGLE_CLIENT_ID'
})
// 准备好后初始化
onLoaded(({ accounts }) => {
accounts.id.initialize({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
callback: handleCredentialResponse
})
})
请参阅注册脚本指南,了解更多高级用法。
GoogleSignInApi
export interface GoogleSignInApi {
accounts: {
id: {
initialize: (config: IdConfiguration) => void
prompt: (momentListener?: (notification: MomentNotification) => void) => void
renderButton: (parent: HTMLElement, options: GsiButtonConfiguration) => void
disableAutoSelect: () => void
cancel: () => void
revoke: (hint: string, callback: (response: RevocationResponse) => void) => void
}
}
}
配置参数结构
您可以通过以下选项配置 Google 登录脚本:
export const GoogleSignInOptions = object({
clientId: string(),
autoSelect: optional(boolean()),
context: optional(union([literal('signin'), literal('signup'), literal('use')])),
useFedcmForPrompt: optional(boolean()),
cancelOnTapOutside: optional(boolean()),
uxMode: optional(union([literal('popup'), literal('redirect')])),
loginUri: optional(string()),
itpSupport: optional(boolean()),
allowedParentOrigin: optional(union([string(), array(string())])),
hd: optional(string()), // 限制登录至 Google Workspace 域
})
示例
One Tap 登录
One Tap 提示提供了简洁的登录体验:
<script setup lang="ts">
const { onLoaded } = useScriptGoogleSignIn()
function handleCredentialResponse(response: CredentialResponse) {
// 将凭证发送到后端进行验证
await $fetch('/api/auth/google', {
method: 'POST',
body: { credential: response.credential }
})
}
onMounted(() => {
onLoaded(({ accounts }) => {
accounts.id.initialize({
client_id: 'YOUR_CLIENT_ID',
callback: handleCredentialResponse,
context: 'signin',
ux_mode: 'popup',
use_fedcm_for_prompt: true // 使用隐私沙箱 FedCM API
})
// 显示 One Tap
accounts.id.prompt()
})
})
</script>
个性化按钮
渲染 Google 的个性化 “使用 Google 登录” 按钮:
<script setup lang="ts">
const { onLoaded } = useScriptGoogleSignIn()
function handleCredentialResponse(response: CredentialResponse) {
console.log('登录成功!', response.credential)
}
onMounted(() => {
onLoaded(({ accounts }) => {
accounts.id.initialize({
client_id: 'YOUR_CLIENT_ID',
callback: handleCredentialResponse
})
const buttonDiv = document.getElementById('g-signin-button')
if (buttonDiv) {
accounts.id.renderButton(buttonDiv, {
type: 'standard',
theme: 'outline',
size: 'large',
text: 'signin_with',
shape: 'rectangular',
logo_alignment: 'left'
})
}
})
})
</script>
<template>
<div id="g-signin-button" />
</template>
状态通知
跟踪 One Tap 的显示状态:
const { onLoaded } = useScriptGoogleSignIn()
onLoaded(({ accounts }) => {
accounts.id.prompt((notification) => {
if (notification.isDisplayMoment()) {
if (notification.isDisplayed()) {
console.log('One Tap 已显示')
} else {
console.log('未显示:', notification.getNotDisplayedReason())
}
}
if (notification.isSkippedMoment()) {
console.log('已跳过:', notification.getSkippedReason())
}
if (notification.isDismissedMoment()) {
console.log('已关闭:', notification.getDismissedReason())
}
})
})
服务器端验证
始终在服务器端验证凭证令牌:
export default defineEventHandler(async (event) => {
const { credential } = await readBody(event)
// 向 Google 验证令牌
const response = await $fetch(`https://oauth2.googleapis.com/tokeninfo`, {
params: { id_token: credential }
})
// 验证客户端 ID 是否匹配
if (response.aud !== 'YOUR_CLIENT_ID') {
throw createError({ statusCode: 401, message: '无效的令牌' })
}
// 使用用户信息创建会话
const user = {
email: response.email,
name: response.name,
picture: response.picture,
sub: response.sub
}
return { user }
})
FedCM API 支持
启用隐私沙箱 FedCM API 支持以增强隐私保护。2025 年 8 月起将强制采用 FedCM。
export default defineNuxtConfig({
scripts: {
registry: {
googleSignIn: {
clientId: 'YOUR_CLIENT_ID',
useFedcmForPrompt: true
}
}
}
})
跨域 iframe
在使用 FedCM 的 One Tap 或登录按钮于跨域 iframe 中时,应为所有父 iframe 添加 allow 属性:
<iframe src="https://your-app.com/login" allow="identity-credentials-get"></iframe>
prompt_parent_id 定制 One Tap 提示的位置。撤销访问权限
允许用户撤销对其 Google 账户的访问权限:
const { onLoaded } = useScriptGoogleSignIn()
function revokeAccess(userId: string) {
onLoaded(({ accounts }) => {
accounts.id.revoke(userId, (response) => {
if (response.successful) {
console.log('访问权限已撤销')
} else {
console.error('撤销失败:', response.error)
}
})
})
}
最佳实践
登出处理
用户登出时务必调用 disableAutoSelect(),防止自动重新认证:
function signOut() {
// 清除应用会话
user.value = null
// 阻止 One Tap 自动选择此账户
onLoaded(({ accounts }) => {
accounts.id.disableAutoSelect()
})
}
限制托管域
限制登录仅允许来自特定 Google Workspace 域的用户:
accounts.id.initialize({
client_id: 'YOUR_CLIENT_ID',
callback: handleCredentialResponse,
hd: 'your-company.com' // 仅允许该域用户登录
})
本地开发配置
要在本地测试 Google 登录:
- 打开 Google Cloud 控制台 → 凭据
- 创建或选择一个 OAuth 2.0 客户端 ID(Web 应用类型)
- 在 授权的 JavaScript 来源 中添加:
http://localhosthttp://localhost:3000(或您的开发服务器端口)
- 保存并复制客户端 ID
http://localhost(而非 127.0.0.1)。使用弹出模式时无需重定向 URI。然后配置环境变量:
NUXT_PUBLIC_SCRIPTS_GOOGLE_SIGN_IN_CLIENT_ID=your-client-id.apps.googleusercontent.com