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

如何在非标准认证令牌端点使用oauth2.clientcredentials?

对接非标准认证令牌端点的Go实现方案

Go标准库的oauth2.ClientCredentials仅适配规范的OAuth2端点,针对这种自定义请求体与响应格式的场景,你可以通过**实现自定义oauth2.TokenSource**完成对接,同时保留自动刷新令牌的能力。

步骤1:定义请求与响应结构体

先匹配目标端点的格式,定义对应的Go结构体:

import (
    "bytes"
    "context"
    "encoding/json"
    "net/http"
    "time"

    "golang.org/x/oauth2"
)

// 自定义认证请求体
type authRequest struct {
    LoginID string `json:"loginId"`
    APIKey  string `json:"apiKey"`
}

// 自定义认证响应体
type authResponse struct {
    Data struct {
        AccessToken string `json:"accessToken"`
        ExpiresIn   int    `json:"expiresIn"`
    } `json:"data"`
}

步骤2:实现自定义TokenSource

实现oauth2.TokenSource接口的Token()方法,负责请求令牌、解析响应并返回标准oauth2.Token:

type customTokenSource struct {
    endpoint string
    loginID  string
    apiKey   string
    client   *http.Client
}

func NewCustomTokenSource(endpoint, loginID, apiKey string) oauth2.TokenSource {
    return &customTokenSource{
        endpoint: endpoint,
        loginID:  loginID,
        apiKey:   apiKey,
        client:   &http.Client{},
    }
}

func (ts *customTokenSource) Token() (*oauth2.Token, error) {
    // 构造请求体
    reqBody, err := json.Marshal(authRequest{
        LoginID: ts.loginID,
        APIKey:  ts.apiKey,
    })
    if err != nil {
        return nil, err
    }

    // 发送POST请求到认证端点
    req, err := http.NewRequest("POST", ts.endpoint, bytes.NewBuffer(reqBody))
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", "application/json")

    resp, err := ts.client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    // 解析响应
    var authResp authResponse
    if err := json.NewDecoder(resp.Body).Decode(&authResp); err != nil {
        return nil, err
    }

    // 转换为标准oauth2.Token,设置过期时间
    expiry := time.Now().Add(time.Duration(authResp.Data.ExpiresIn) * time.Second)
    return &oauth2.Token{
        AccessToken: authResp.Data.AccessToken,
        Expiry:      expiry,
    }, nil
}

步骤3:创建自动刷新的HTTP客户端

用自定义的TokenSource包裹一层oauth2.ReuseTokenSource,即可实现令牌过期自动刷新:

func main() {
    tokenSource := NewCustomTokenSource(
        "https://your-auth-endpoint.com/token",
        "apiClient",
        "F7694C56886933570EE1B03FAC2CD80671E57586",
    )
    // 自动复用有效令牌,过期时自动刷新
    autoRefreshSource := oauth2.ReuseTokenSource(nil, tokenSource)
    client := oauth2.NewClient(context.Background(), autoRefreshSource)

    // 使用client发送业务请求,会自动带上有效令牌
    resp, err := client.Get("https://your-api-endpoint.com/data")
    if err != nil {
        // 处理错误
    }
    defer resp.Body.Close()
}

关键说明

  • ReuseTokenSource会自动缓存未过期的令牌,当令牌过期时,自动调用自定义TokenSource的Token()方法获取新令牌
  • 自定义TokenSource完全控制认证请求的格式和响应解析,可适配任意非标准端点

内容的提问来源于stack exchange,提问作者Scott Deerwester

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:25:26