218 lines
5.2 KiB
Go
218 lines
5.2 KiB
Go
|
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, "&")
|
||
|
}
|