
使用Node.js、Express和MySQL構建REST API
在這段代碼中,generateSignature 函數用來生成簽名。注意,我們使用了HMAC-SHA256算法來確保簽名的安全性。這種方法不僅可靠,而且易于實現。
接下來是服務器端的實現,服務器會從請求中提取簽名,并根據相同的算法重新生成簽名,然后進行對比。
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"
)
// 生成簽名的函數
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))
}
// 驗證簽名的函數
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)
}
服務器端的validateSignature函數用來驗證簽名,首先提取出請求中的簽名、時間戳等信息,然后根據與客戶端相同的算法重新生成簽名,并與請求中的簽名對比。如果兩者一致,則表示請求合法。
簽名驗證不僅能防止請求被篡改,還能有效防止重放攻擊(Replay Attack)。通過驗證時間戳,我們可以確保請求是在一個合理的時間范圍內發送的,防止有人惡意重復發送相同的請求。
在實際開發中,這種簽名驗證機制雖然看起來步驟繁瑣,但卻是確保API安全性的重要措施之一。通過合理設計和實現,簽名驗證可以在不顯著增加系統負擔的前提下,大幅提升API的安全性。
在API開發中,簽名驗證是不可或缺的一環。通過合理的密鑰管理、簽名生成和驗證機制,我們可以確保每一個請求的完整性和可靠性。作為一個程序員,掌握這種技術不僅能讓你的API更加安全,也能讓你在面對潛在的安全威脅時更加從容。
好了,今天就聊到這里。如果你有任何問題或者想法,歡迎在評論區和我討論。我們下次再見,祝大家編程愉快!
文章轉自微信公眾號@Go語言教程