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

如何在Go Google API刷新AccessToken和RefreshToken时接收通知?

在Go Google API中监听Token变更并持久化到数据库

当使用Go Google API库时,要在Token自动刷新后将新Token同步到数据库,核心是通过**自定义oauth2.TokenSource**拦截Token的获取/刷新操作,在拿到新Token时触发持久化逻辑。

实现步骤

  1. 定义包装类实现oauth2.TokenSource接口,拦截Token获取结果并触发保存逻辑:
import (
    "context"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "google.golang.org/api/drive/v3"
    "time"
)

// 自定义TokenSource,用于在Token更新时保存到数据库
type savingTokenSource struct {
    oauth2.TokenSource       // 嵌套原始TokenSource,继承其自动刷新逻辑
    saveFunc func(*oauth2.Token) error // 数据库保存回调
}

// Token 重写Token方法,拦截Token获取流程
func (s *savingTokenSource) Token() (*oauth2.Token, error) {
    // 调用原始TokenSource获取Token(自动处理过期刷新)
    token, err := s.TokenSource.Token()
    if err != nil {
        return nil, err
    }

    // 将新Token同步到数据库
    if err := s.saveFunc(token); err != nil {
        return nil, err
    }

    return token, nil
}
  1. 构建自定义TokenSource并创建API客户端:
func main() {
    // 1. 从数据库读取用户初始Token
    initialToken := &oauth2.Token{
        AccessToken:  "用户已存的AccessToken",
        RefreshToken: "用户已存的RefreshToken",
        Expiry:       time.Now().Add(-time.Hour), // 模拟Token过期状态
    }

    // 2. 配置OAuth2基础参数
    config := &oauth2.Config{
        ClientID:     "你的客户端ID",
        ClientSecret: "你的客户端密钥",
        RedirectURL:  "你的回调地址",
        Scopes:       []string{drive.DriveFileScope}, // 根据业务需求设置权限范围
        Endpoint:     google.Endpoint,
    }

    // 3. 创建原始TokenSource(自带自动刷新逻辑)
    originalTS := config.TokenSource(context.Background(), initialToken)

    // 4. 实现Token保存到数据库的逻辑(替换为你的实际数据库操作)
    saveToDB := func(token *oauth2.Token) error {
        // 示例:更新数据库中对应用户的Token记录
        // _, err := db.Exec("UPDATE users SET access_token=?, refresh_token=?, expiry=? WHERE id=?",
        //     token.AccessToken, token.RefreshToken, token.Expiry, userID)
        // return err
        return nil
    }

    // 5. 包装为带缓存+保存逻辑的TokenSource,避免重复刷新和无效写入
    cachedTS := oauth2.ReuseTokenSource(initialToken, originalTS)
    savingTS := &savingTokenSource{
        TokenSource: cachedTS,
        saveFunc:    saveToDB,
    }

    // 6. 创建带自定义TokenSource的HTTP客户端
    client := oauth2.NewClient(context.Background(), savingTS)

    // 7. 创建Google API服务(以Drive为例)
    driveSvc, err := drive.New(client)
    if err != nil {
        panic(err)
    }

    // 后续使用driveSvc发起请求时,Token过期会自动刷新,新Token会同步到数据库
}

关键注意事项

  • ReuseTokenSource会缓存有效Token,仅当Token过期时触发刷新,减少不必要的网络请求和数据库操作。
  • 保存Token时建议做幂等校验:对比数据库中现有Token,仅当AccessToken/RefreshToken/Expiry发生变化时执行更新,降低数据库写入压力。
  • 并发场景处理:若多个请求同时触发Token刷新,可能导致重复保存,可通过加锁或数据库乐观锁避免冲突。

谷歌官方文档(OAuth2 Web服务器流程-离线访问)翻译

当应用需要在用户未主动操作的情况下访问Google API时,必须请求离线访问权限。此时Google会返回刷新令牌,应用可通过该令牌获取新的访问令牌,无需用户再次授权:

  • 请求离线访问时,需在构建授权URL时添加access_type=offline参数。
  • 若用户已授权过应用,但之前未请求离线访问,再次发起授权时需添加prompt=consent参数,才能获取刷新令牌。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:05:28