优化与代理服务的密钥存储与传递方式;更新套餐,账单查询对长效套餐的支持,新增长效套餐分页查询接口
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
package globals
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -29,15 +34,19 @@ type ProxyPermitConfig struct {
|
||||
Expire time.Time `json:"expire"`
|
||||
}
|
||||
|
||||
func (p *ProxyClient) Permit(proxy string, config []*ProxyPermitConfig) error {
|
||||
func (p *ProxyClient) Permit(host string, secret string, config []*ProxyPermitConfig) error {
|
||||
|
||||
str, err := json.Marshal(config)
|
||||
// 请求体加密
|
||||
body, err := encrypt(config, secret)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("加密请求失败: %w", err)
|
||||
}
|
||||
|
||||
body := strings.NewReader(string(str))
|
||||
resp, err := http.Post(fmt.Sprintf("%s:8848%s", proxy, PermitEndpoint), "application/json", body)
|
||||
resp, err := http.Post(
|
||||
fmt.Sprintf("http://%s:8848%s", host, PermitEndpoint),
|
||||
"application/json",
|
||||
strings.NewReader(body),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -49,3 +58,61 @@ func (p *ProxyClient) Permit(proxy string, config []*ProxyPermitConfig) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encrypt(req []*ProxyPermitConfig, secretStr string) (string, error) {
|
||||
var encoding = base32.StdEncoding.WithPadding(base32.NoPadding)
|
||||
|
||||
// 创建 AES 密钥
|
||||
secret, err := encoding.DecodeString(secretStr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("解码 AES 密钥字符串失败: %w", err)
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(secret)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建 AES 密钥失败: %w", err)
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建 AES GCM 失败: %w", err)
|
||||
}
|
||||
|
||||
// 加密内容
|
||||
bytes, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("配置参数序列化失败: %w", err)
|
||||
}
|
||||
|
||||
nonceBytes := make([]byte, gcm.NonceSize())
|
||||
if _, err := rand.Read(nonceBytes); err != nil {
|
||||
return "", fmt.Errorf("生成随机数失败: %w", err)
|
||||
}
|
||||
nonce := base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(nonceBytes)
|
||||
|
||||
timestamp := time.Now().UnixMilli()
|
||||
aad := fmt.Sprintf("%s:%d", nonce, timestamp)
|
||||
|
||||
ciphertext := gcm.Seal(nil, nonceBytes, bytes, []byte(aad))
|
||||
encoded := base64.StdEncoding.EncodeToString(ciphertext)
|
||||
|
||||
// 生成请求体
|
||||
encrypted := EncryptReq{
|
||||
Content: encoded,
|
||||
Nonce: nonce,
|
||||
Timestamp: timestamp,
|
||||
}
|
||||
|
||||
body, err := json.Marshal(encrypted)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("请求参数序列化失败: %w", err)
|
||||
}
|
||||
|
||||
return string(body), nil
|
||||
}
|
||||
|
||||
type EncryptReq struct {
|
||||
Content string `json:"content"`
|
||||
Nonce string `json:"nonce"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user