import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
)

// 生成簽名的函數(shù)
func generateSignature(apiSecret, apiKey, timestamp, nonce string, params url.Values) string {
message := apiKey + timestamp + nonce + params.Encode() // 拼接字符串
mac := hmac.New(sha256.New, []byte(apiSecret)) // 使用HMAC-SHA256算法
mac.Write([]byte(message))
signature := hex.EncodeToString(mac.Sum(nil)) // 生成簽名
return signature
}

func main() {
apiKey := "your_api_key"
apiSecret := "your_api_secret"
timestamp := strconv.FormatInt(time.Now().Unix(), 10) // 當(dāng)前時間戳
nonce := "random_nonce" // 隨機(jī)數(shù)

// 構(gòu)造請求參數(shù)
params := url.Values{}
params.Set("param1", "value1")
params.Set("param2", "value2")

// 生成簽名
signature := generateSignature(apiSecret, apiKey, timestamp, nonce, params)

// 創(chuàng)建HTTP請求
req, err := http.NewRequest("GET", "http://example.com/api", nil)
if err != nil {
fmt.Println("Error creating request:", err)
return
}

// 將簽名和其他參數(shù)添加到請求中
query := req.URL.Query()
query.Add("apiKey", apiKey)
query.Add("timestamp", timestamp)
query.Add("nonce", nonce)
query.Add("signature", signature)
req.URL.RawQuery = query.Encode()

// 發(fā)送請求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error making request:", err)
return
}
defer resp.Body.Close()

fmt.Println("Response status:", resp.Status)
}

在這段代碼中,generateSignature 函數(shù)用來生成簽名。注意,我們使用了HMAC-SHA256算法來確保簽名的安全性。這種方法不僅可靠,而且易于實(shí)現(xiàn)。

服務(wù)器端:驗(yàn)證簽名并響應(yīng)請求

接下來是服務(wù)器端的實(shí)現(xiàn),服務(wù)器會從請求中提取簽名,并根據(jù)相同的算法重新生成簽名,然后進(jìn)行對比。

package main

import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
)

const (
apiKey = "your_api_key"
apiSecret = "your_api_secret"
)

// 生成簽名的函數(shù)
func generateSignature(apiSecret, apiKey, timestamp, nonce string, params url.Values) string {
message := apiKey + timestamp + nonce + params.Encode()
mac := hmac.New(sha256.New, []byte(apiSecret))
mac.Write([]byte(message))
return hex.EncodeToString(mac.Sum(nil))
}

// 驗(yàn)證簽名的函數(shù)
func validateSignature(r *http.Request) bool {
apiKey := r.URL.Query().Get("apiKey")
timestamp := r.URL.Query().Get("timestamp")
nonce := r.URL.Query().Get("nonce")
signature := r.URL.Query().Get("signature")

if apiKey != apiKey {
return false
}

timeInt, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil {
return false
}

if time.Now().Unix()-timeInt > 300 { // 檢查時間戳,防止重放攻擊
return false
}

params := r.URL.Query()
params.Del("signature")

expectedSignature := generateSignature(apiSecret, apiKey, timestamp, nonce, params)

return hmac.Equal([]byte(signature), []byte(expectedSignature))
}

func handler(w http.ResponseWriter, r *http.Request) {
if !validateSignature(r) {
http.Error(w, "Invalid signature", http.StatusUnauthorized)
return
}

fmt.Fprintf(w, "Request is authenticated")
}

func main() {
http.HandleFunc("/api", handler)
http.ListenAndServe(":8080", nil)
}

服務(wù)器端的validateSignature函數(shù)用來驗(yàn)證簽名,首先提取出請求中的簽名、時間戳等信息,然后根據(jù)與客戶端相同的算法重新生成簽名,并與請求中的簽名對比。如果兩者一致,則表示請求合法。

簽名驗(yàn)證的優(yōu)勢

簽名驗(yàn)證不僅能防止請求被篡改,還能有效防止重放攻擊(Replay Attack)。通過驗(yàn)證時間戳,我們可以確保請求是在一個合理的時間范圍內(nèi)發(fā)送的,防止有人惡意重復(fù)發(fā)送相同的請求。

在實(shí)際開發(fā)中,這種簽名驗(yàn)證機(jī)制雖然看起來步驟繁瑣,但卻是確保API安全性的重要措施之一。通過合理設(shè)計和實(shí)現(xiàn),簽名驗(yàn)證可以在不顯著增加系統(tǒng)負(fù)擔(dān)的前提下,大幅提升API的安全性。

小結(jié)

API開發(fā)中,簽名驗(yàn)證是不可或缺的一環(huán)。通過合理的密鑰管理、簽名生成和驗(yàn)證機(jī)制,我們可以確保每一個請求的完整性和可靠性。作為一個程序員,掌握這種技術(shù)不僅能讓你的API更加安全,也能讓你在面對潛在的安全威脅時更加從容。

好了,今天就聊到這里。如果你有任何問題或者想法,歡迎在評論區(qū)和我討論。我們下次再見,祝大家編程愉快!

文章轉(zhuǎn)自微信公眾號@Go語言教程

上一篇:

從哪些標(biāo)準(zhǔn)評估API的性能和質(zhì)量

下一篇:

通過負(fù)面測試構(gòu)建更具彈性的API
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實(shí)測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費(fèi)

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費(fèi)