如何在 Go 中使用 OAuth2 正确获取 Google 用户邮箱-Golang

本文详解如何在 golang 中通过 google oauth2 安全、可靠地获取用户邮箱地址,涵盖正确构造授权 url、交换令牌、调用 userinfo 端点、解析响应体等关键步骤,并澄清 `oauth2.config` 的线程安全与复用机制。

在 Go 中集成 Google OAuth2 获取用户邮箱时,一个常见误区是忽略了 HTTP 响应体(response.Body)需要显式读取并关闭——直接打印 response 结构体只会看到空的 Body: {},而真实数据实际存在于流式响应体中。此外,Google 已全面弃用 Google+ API(如 /plus/v1/people/me),推荐使用标准 OpenID Connect 流程,即通过 https://www.googleapis.com/oauth2/v3/userinfo 或更规范的动态发现端点获取用户信息。

✅ 正确流程:OpenID Connect 方式(推荐)

首先确保 oauth2.Config 使用标准 OIDC 作用域:

provider := oauth2.Config{
    ClientID:     "your-client-id.apps.googleusercontent.com",
    ClientSecret: "your-client-secret",
    RedirectURL:  "https://yourdomain.com/callback",
    Endpoint:     google.Endpoint,
    Scopes: []string{
        "https://www.googleapis.com/auth/userinfo.email",
        "https://www.googleapis.com/auth/userinfo.profile", // 可选,用于 name/picture
        "openid", // 必须启用 OpenID Connect
    },
}

⚠️ 注意:openid 是必需 scope,否则 userinfo 端点可能拒绝请求或返回不完整数据。

生成授权 URL 并处理回调后,完成令牌交换:

tok, err := provider.Exchange(ctx, authCode) // ✅ 使用 context(替代已废弃的 oauth2.NoContext)
if err != nil {
    http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError)
    return
}

client := provider.Client(ctx, tok)

关键一步:调用 UserInfo 端点并读取响应体

// ✅ 正确端点(无需手动拼接,直接使用标准 OIDC userinfo endpoint)
userInfoURL := "https://www.googleapis.com/oauth2/v3/userinfo"

resp, err := client.Get(userInfoURL)
if err != nil {
    http.Error(w, "Failed to fetch user info: "+err.Error(), http.StatusInternalServerError)
    return
}
defer resp.Body.Close() // ✅ 必须关闭 Body

body, err := io.ReadAll(resp.Body) // ✅ 显式读取全部响应内容
if err != nil {
    http.Error(w, "Failed to read response body: "+err.Error(), http.StatusInternalServerError)
    return
}

// 解析 JSON
var userInfo struct {
    Email      string `json:"email"`
    EmailVerified bool `json:"email_verified"`
    Name       string `json:"name"`
    Picture    string `json:"picture"`
}
if err := json.Unmarshal(body, &userInfo); err != nil {
    http.Error(w, "Failed to parse user info: "+err.Error(), http.StatusInternalServerError)
    return
}

log.Printf("User email: %s (verified: %t)", userInfo.Email, userInfo.EmailVerified)

? 进阶:使用 OpenID Connect 发现文档(更健壮)

为提升兼容性与未来可维护性,可先获取 Google 的 OpenID 配置(.well-known/openid-configuration),再从中提取 userinfo_endpoint:

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » 如何在 Go 中使用 OAuth2 正确获取 Google 用户邮箱-Golang
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3992296+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1391+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 3992297+
  • 本周更新: 0+
  • 最后更新: 2026-03-16