Files
zmkgC/third/securityRequest.go
2025-07-07 20:11:59 +08:00

115 lines
3.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package utility 安全请求思路来源https://blog.csdn.net/David_jiahuan/article/details/106391956
// @Author 铁憨憨[cory] 2024/9/11 9:38:00
package utility
import (
"crypto/md5"
"crypto/sha256"
"encoding/hex"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gconv"
"math/big"
"strconv"
"time"
)
// 签名验证中间件
func SignatureMiddleware(r *ghttp.Request) {
if r.URL.Path == "/zm/api/wxApplet/wxApplet/appPort/releaseAppVersion" {
r.Middleware.Next()
return
}
// 获取请求中的参数
signature := gconv.String(r.Header.Get("sign"))
timestamp := gconv.Int64(r.Header.Get("timestamp"))
nonce := gconv.String(r.Header.Get("nonce"))
if signature == "" || timestamp == 0 || nonce == "" {
r.Response.WriteJson(g.Map{"error": "无效验证"})
r.ExitAll()
return
}
//验证时间戳
if !validateTimestamp(timestamp) {
r.Response.WriteJson(g.Map{"error": "请求过期"})
r.ExitAll()
return
}
// 验证 nonce 防止重放攻击
if !validateNonce(nonce) {
r.Response.WriteJson(g.Map{"error": "无效请求:检测到重放"})
r.ExitAll()
return
}
serverSignature := generateServerSignature(strconv.FormatInt(timestamp, 10), nonce)
// 验证签名
if signature != serverSignature {
r.Response.WriteJson(g.Map{"error": "签名错误"})
r.ExitAll()
return
}
//签名验证通过
r.Middleware.Next()
}
func validateTimestamp(unixTimestamp int64) bool {
// 获取当前时间
now := time.Now().UnixMilli()
result := subtractBigFromInt64(now, unixTimestamp)
// 将整数 1500 转换为 *big.Int 类型
big1500 := big.NewInt(30000)
// 验证时间差是否在 1500 毫秒内
if result.Cmp(big1500) == -1 && result.Cmp(big.NewInt(0)) >= 0 {
return true
}
return false
}
func subtractBigFromInt64(currentMillis int64, unixTimestamp int64) *big.Int {
// 将两个 int64 类型的值转换为 *big.Int 类型
bigCurrent := big.NewInt(currentMillis)
bigUnixTimestamp := big.NewInt(unixTimestamp)
// 计算差值
result := big.NewInt(0).Sub(bigCurrent, bigUnixTimestamp)
// 求差值的绝对值
return result.Abs(result)
}
// 验证 nonce
func validateNonce(nonce string) bool {
nonceKey := "reset" + nonce
// 使用 Redis 来存储 nonce防止重放
redisClient := g.Redis()
ctx := gctx.New()
exists, err := redisClient.Exists(ctx, nonceKey)
if err != nil {
return false
}
if exists > 0 {
return false // nonce 已经存在,说明是重放请求
}
// nonce 不存在,存储到 Redis 并设置60秒过期时间
err = redisClient.SetEX(ctx, nonceKey, nonce, 60)
if err != nil {
return false
} else {
return true
}
}
// 生成服务端签名
func generateServerSignature(timestamp, nonce string) string {
sum := md5.Sum([]byte("coyrOrtiehanhan1223202409111457"))
md5Sum := hex.EncodeToString(sum[:])
// 拼接时间戳、nonce 和 secretKey
signStr := md5Sum + timestamp + nonce
// 对拼接后的字符串进行 MD5 加密
md5Hash := md5.Sum([]byte(signStr))
md5Hex := hex.EncodeToString(md5Hash[:])
// 对 MD5 结果进行 SHA-256 加密
sha256Hash := sha256.Sum256([]byte(md5Hex))
sha256Hex := hex.EncodeToString(sha256Hash[:])
return sha256Hex
}