Golang单脚OAuth1的实现与问题讨论
Golang单脚OAuth1的实现与问题讨论 我正在尝试生成一个令牌,以便能够进行单腿 OAuth 1 API 调用,但我很难理解如何在 Golang 中实现。
我也找不到相关的包。希望有人能帮助我。
我尝试在 Postman 中使其正常工作,这运行得很好。
req.Header.Add("Authorization", "OAuth oauth_consumer_key=\"xxxx\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1712582585\",oauth_nonce=\"xxxx\",oauth_version=\"1.0\",oauth_signature=\"xxxx\"")
但现在我需要将其转换为 Golang。我拥有的数据是一个 authentication_key 和一个 authentication_secret。
这就是我进行 API 调用所需的全部内容。
希望有人能帮助我了解如何创建带有正确签名的请求。
我尝试寻找相关的包,但据我所见,没有一个支持单腿 OAuth 1 调用。
更多关于Golang单脚OAuth1的实现与问题讨论的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
您将需要以下标准的 Go 语言库:
net/http用于发起 HTTP 请求。crypto/hmac和crypto/sha1用于生成 HMAC-SHA1 签名。url用于 URL 编码。time用于生成时间戳。
更多关于Golang单脚OAuth1的实现与问题讨论的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
对于单腿OAuth 1的实现,可以使用oauth1包配合自定义签名方法。以下是一个完整的示例:
package main
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"net/http"
"strconv"
"time"
"math/rand"
"strings"
)
// 生成OAuth 1.0a签名
func generateSignature(method, url, consumerSecret string, params map[string]string) string {
// 1. 收集参数
paramString := ""
for k, v := range params {
if paramString != "" {
paramString += "&"
}
paramString += fmt.Sprintf("%s=%s", k, v)
}
// 2. 构建签名基础字符串
signatureBase := strings.ToUpper(method) + "&" +
percentEncode(url) + "&" +
percentEncode(paramString)
// 3. 生成签名密钥(单腿OAuth只需要consumer_secret)
signingKey := percentEncode(consumerSecret) + "&"
// 4. 计算HMAC-SHA1
mac := hmac.New(sha1.New, []byte(signingKey))
mac.Write([]byte(signatureBase))
signature := mac.Sum(nil)
// 5. Base64编码
return base64.StdEncoding.EncodeToString(signature)
}
// URL编码(符合OAuth规范)
func percentEncode(s string) string {
return strings.ReplaceAll(
strings.ReplaceAll(
strings.ReplaceAll(s, "%", "%25"),
"+", "%2B",
),
" ", "%20",
)
}
// 生成随机nonce
func generateNonce() string {
return fmt.Sprintf("%d", rand.Int63())
}
// 创建OAuth 1.0a头部
func createOAuthHeader(consumerKey, consumerSecret, method, url string) string {
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
nonce := generateNonce()
params := map[string]string{
"oauth_consumer_key": consumerKey,
"oauth_nonce": nonce,
"oauth_signature_method": "HMAC-SHA1",
"oauth_timestamp": timestamp,
"oauth_version": "1.0",
}
signature := generateSignature(method, url, consumerSecret, params)
return fmt.Sprintf(
`OAuth oauth_consumer_key="%s",oauth_nonce="%s",oauth_signature="%s",oauth_signature_method="HMAC-SHA1",oauth_timestamp="%s",oauth_version="1.0"`,
consumerKey,
nonce,
percentEncode(signature),
timestamp,
)
}
func main() {
consumerKey := "your_authentication_key"
consumerSecret := "your_authentication_secret"
apiURL := "https://api.example.com/endpoint"
// 创建请求
req, err := http.NewRequest("GET", apiURL, nil)
if err != nil {
panic(err)
}
// 添加OAuth头部
oauthHeader := createOAuthHeader(consumerKey, consumerSecret, "GET", apiURL)
req.Header.Add("Authorization", oauthHeader)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
如果需要使用现有的包,可以使用github.com/dghubble/oauth1并自定义Token:
package main
import (
"github.com/dghubble/oauth1"
"net/http"
"fmt"
)
func main() {
config := oauth1.Config{
ConsumerKey: "your_authentication_key",
ConsumerSecret: "your_authentication_secret",
// 单腿OAuth不需要回调URL
CallbackURL: "",
// 单腿OAuth不需要Endpoint
Endpoint: oauth1.Endpoint{},
}
// 创建单腿OAuth Token(无Token和Secret)
token := oauth1.NewToken("", "")
// 创建HTTP客户端
httpClient := config.Client(oauth1.NoContext, token)
// 发送请求
resp, err := httpClient.Get("https://api.example.com/endpoint")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
对于更复杂的场景(如包含查询参数),需要调整签名生成逻辑:
func generateSignatureWithQueryParams(method, baseURL, queryString, consumerSecret string, oauthParams map[string]string) string {
// 合并所有参数
allParams := make(map[string]string)
// 添加OAuth参数
for k, v := range oauthParams {
allParams[k] = v
}
// 解析并添加查询参数
if queryString != "" {
pairs := strings.Split(queryString, "&")
for _, pair := range pairs {
kv := strings.Split(pair, "=")
if len(kv) == 2 {
allParams[kv[0]] = kv[1]
}
}
}
// 生成参数字符串(按键排序)
keys := make([]string, 0, len(allParams))
for k := range allParams {
keys = append(keys, k)
}
sort.Strings(keys)
paramString := ""
for _, k := range keys {
if paramString != "" {
paramString += "&"
}
paramString += fmt.Sprintf("%s=%s", k, percentEncode(allParams[k]))
}
// 继续签名生成...
// ...(使用之前的generateSignature函数逻辑)
}
这些示例展示了如何在Golang中实现单腿OAuth 1.0a认证。第一个示例提供了完整的底层实现,第二个示例展示了如何使用现有包进行简化。

