如何在非标准认证令牌端点使用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
相关产品推荐
相关产品推荐

