api/commonSigner.go

218 lines
5.2 KiB
Go
Raw Normal View History

2025-09-11 23:42:22 +08:00
package plugin
import (
"crypto/rsa"
"encoding/base64"
"errors"
"fmt"
"net/url"
"sort"
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
)
// 基本认证签名器
func makeBasicAuthSign(req *Request, cfg *SignerConfig) error {
// 1. 获取用户名和密码
username := cfg.String("username", "")
password := cfg.String("password", "")
// 2. 构造认证字符串
auth := username + ":" + password
encoded := base64.StdEncoding.EncodeToString([]byte(auth))
// 3. 添加认证头
req.Headers["Authorization"] = "Basic " + encoded
return nil
}
// Bearer Token认证
func makeBearerSign(req *Request, cfg *SignerConfig) error {
req.Headers["Authorization"] = "Bearer " + cfg.String("key", "")
return nil
}
// 通用JWT签名器
func makeJWTSign(req *Request, cfg *SignerConfig) error {
// 1. 获取JWT配置
secret := cfg.String("secret", "")
algorithm := cfg.String("algorithm", "HS256")
expires := cfg.Int("expires", 3600) // 默认1小时有效期
timeuint := cfg.String("timeuint", "s") // 时间戳单位
// 2. 创建Claims
var tm, exp int64
if timeuint == "ms" {
tm = time.Now().UnixMilli()
exp = tm + expires*1000
} else {
tm = time.Now().Unix()
exp = tm + expires
}
claims := jwt.MapClaims{
"exp": exp,
"iat": tm,
}
// 3. 添加自定义声明
for k, v := range cfg.Map("claims") {
if v == "{{timestamp}}" {
claims[k] = tm
} else {
claims[k] = v
}
}
// fmt.Println(u.BMagenta(u.JsonP(claims)), algorithm)
// 4. 创建Token
var token *jwt.Token
switch algorithm {
case "HS256":
token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
case "HS384":
token = jwt.NewWithClaims(jwt.SigningMethodHS384, claims)
case "HS512":
token = jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
case "RS256":
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
default:
// 默认使用HS256
token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
}
token.Header["alg"] = algorithm
for k, v := range cfg.Map("jwtHeader") {
token.Header[k] = v
}
// fmt.Println(u.BYellow(u.JsonP(token.Header)), "===")
// 5. 签名Token
var signedString string
var err error
if strings.HasPrefix(algorithm, "HS") {
signedString, err = token.SignedString([]byte(secret))
} else if strings.HasPrefix(algorithm, "RS") {
// 处理RSA私钥
if privateKey := cfg.String("privateKey", ""); privateKey != "" {
var prikey *rsa.PrivateKey
prikey, err = jwt.ParseRSAPrivateKeyFromPEM([]byte(privateKey))
if err == nil {
signedString, err = token.SignedString(prikey)
}
} else {
err = errors.New("privateKey is empty")
}
}
if err != nil {
// 处理错误
return err
}
// 6. 添加认证头
prefix := cfg.String("prefix", "Bearer ")
req.Headers["Authorization"] = prefix + signedString
return nil
}
// // 通用HMAC-SHA256签名器
// func makeHmacSign(req *Request, cfg *SignerConfig) error {
// hashMethod := strings.ToUpper(cfg.String("hashMethod", "SHA256"))
// // 1. 获取待签名数据
// dataToSign := cfg.String("signData", "")
// if dataToSign == "" {
// // 默认使用HTTP方法+URL+当前时间戳
// timestamp := time.Now().Format(time.RFC3339)
// dataToSign = req.Method + " " + req.Url + "\n" + timestamp
// cfg.Set("timestamp", timestamp)
// }
// // 2. 计算签名
// key := []byte(cfg.String("secret", ""))
// var h hash.Hash
// switch hashMethod {
// case "SHA1":
// h = hmac.New(sha1.New, key)
// case "SHA256":
// h = hmac.New(sha256.New, key)
// case "SHA384":
// h = hmac.New(sha512.New384, key)
// case "SHA512":
// h = hmac.New(sha512.New, key)
// default:
// h = hmac.New(sha256.New, key)
// }
// h.Write([]byte(dataToSign))
// signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
// // 3. 添加到请求
// headerName := cfg.String("headerName", "X-Signature")
// req.Headers[headerName] = signature
// // 4. 可选: 添加时间戳
// timestamp := cfg.String("timestamp", "")
// if timestamp != "" {
// tsHeader := cfg.String("tsHeader", "X-Timestamp")
// req.Headers[tsHeader] = timestamp
// }
// return nil
// }
func SortParams(params map[string]string, allow *[]string, deny *[]string) (paramsList string, paramsPairs string) {
if len(params) == 0 {
return "", ""
}
// 获取排序的key
keys := make([]string, 0)
for k := range params {
// 按白名单过滤
if allow != nil {
isAllow := false
for _, a := range *allow {
if a == k || (strings.HasSuffix(a, "*") && strings.HasPrefix(k, a[:len(a)-1])) {
isAllow = true
}
}
if !isAllow {
continue
}
}
// 按黑名单过滤
if deny != nil {
isDeny := false
for _, d := range *deny {
if d == k || (strings.HasSuffix(d, "*") && strings.HasPrefix(k, d[:len(d)-1])) {
isDeny = true
}
}
if isDeny {
continue
}
}
keys = append(keys, k)
}
sort.Strings(keys)
// 构建urlParamList和httpParameters
paramList := make([]string, 0, len(keys))
paramPairs := make([]string, 0, len(keys))
for _, k := range keys {
paramList = append(paramList, strings.ToLower(url.QueryEscape(k)))
paramPairs = append(paramPairs, fmt.Sprintf("%s=%s",
strings.ToLower(url.QueryEscape(k)),
url.QueryEscape(params[k])))
}
return strings.Join(paramList, ";"), strings.Join(paramPairs, "&")
}