优化签名规则
This commit is contained in:
@@ -0,0 +1 @@
|
||||
*.log
|
||||
@@ -1,37 +1,49 @@
|
||||
package bopx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"code.yun.ink/pkg/convx"
|
||||
"github.com/yuninks/loggerx"
|
||||
)
|
||||
|
||||
// 缺点
|
||||
// 1.值必须是字符串,数组/对象这些不允许,或者需要通过一定规则转成字符串
|
||||
|
||||
type apix struct {
|
||||
ingoreKey []string
|
||||
signKey string
|
||||
}
|
||||
|
||||
func NewApi(ignoreKey []string, signKey string) *apix {
|
||||
return &apix{
|
||||
ingoreKey: ignoreKey,
|
||||
signKey: signKey,
|
||||
}
|
||||
}
|
||||
|
||||
// 签名规则
|
||||
// 1.除掉不参与签名的用户参数
|
||||
// 1.所有参数的key根据字典排序
|
||||
// 2.根据key=val&key2=val2的格式组装字符串
|
||||
// 3.后面拼接用户签名key `&key=xxxx`得道新字符串
|
||||
// 4.把新字符串用md5加密并转大写的道签名的值
|
||||
func (l *apix) GetSign(params map[string]interface{}) (sign string, err error) {
|
||||
for _, val := range l.ingoreKey {
|
||||
|
||||
// 缺点
|
||||
// 1.值必须是字符串,数组/对象这些不允许,或者需要通过一定规则转成字符串
|
||||
|
||||
type apix struct {
|
||||
logger loggerx.LoggerInterface
|
||||
ignoreKeys []string
|
||||
}
|
||||
|
||||
func NewApi(opts ...Option) *apix {
|
||||
options := newOptions(opts...)
|
||||
return &apix{
|
||||
logger: options.logger,
|
||||
ignoreKeys: options.ignoreKeys,
|
||||
}
|
||||
}
|
||||
|
||||
// 计算签名值
|
||||
func (l *apix) GetSign(ctx context.Context, signKey string, params map[string]any) (sign string, err error) {
|
||||
if signKey == "" {
|
||||
return "", ErrorSignKeyIsEmpty
|
||||
}
|
||||
if len(params) == 0 {
|
||||
return "", ErrorSignParamIsEmpty
|
||||
}
|
||||
|
||||
for _, val := range l.ignoreKeys {
|
||||
delete(params, val)
|
||||
}
|
||||
|
||||
@@ -48,21 +60,19 @@ func (l *apix) GetSign(params map[string]interface{}) (sign string, err error) {
|
||||
if k > 0 {
|
||||
str = str + "&"
|
||||
}
|
||||
val, err := convx.ToString(params[v])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
val := convx.ToString(params[v])
|
||||
str = str + v + "=" + val
|
||||
}
|
||||
str = str + "&key=" + l.signKey
|
||||
str = str + "&key=" + signKey
|
||||
data := []byte(str)
|
||||
has := md5.Sum(data)
|
||||
md5str1 := fmt.Sprintf("%x", has) // []byte转16进制
|
||||
sign = strings.ToUpper(md5str1)
|
||||
l.logger.Infof(ctx, "bopx sign Str:%s sign:%s", str, sign)
|
||||
return sign, nil
|
||||
}
|
||||
|
||||
func (l *apix) Verify(params map[string]interface{}) error {
|
||||
func (l *apix) Verify(ctx context.Context, signKey string, params map[string]interface{}) error {
|
||||
|
||||
sign, ok := params["sign"]
|
||||
if !ok {
|
||||
@@ -72,7 +82,7 @@ func (l *apix) Verify(params map[string]interface{}) error {
|
||||
if !ok {
|
||||
return ErrorSignMustBeString
|
||||
}
|
||||
g_sign, err := l.GetSign(params)
|
||||
g_sign, err := l.GetSign(ctx, signKey, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
package bopx_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"code.yun.ink/pkg/bopx"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestApiGetSign 测试API签名生成
|
||||
func TestApiGetSign(t *testing.T) {
|
||||
// 测试用例1: 基本参数签名
|
||||
params := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
}
|
||||
|
||||
api := bopx.NewApi()
|
||||
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign returned error: %v", err)
|
||||
}
|
||||
|
||||
expectedSign := "F84C5DF671D8279B57AC6EED2C140407" // 根据算法计算得出的预期值
|
||||
if sign != expectedSign {
|
||||
t.Errorf("GetSign() = %v, want %v", sign, expectedSign)
|
||||
}
|
||||
|
||||
// 记录生成的签名值
|
||||
t.Logf("Generated sign: %s", sign)
|
||||
}
|
||||
|
||||
// TestApiVerify 测试API签名验证
|
||||
func TestApiVerify(t *testing.T) {
|
||||
// 测试用例1: 正确签名验证
|
||||
params := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
}
|
||||
|
||||
api := bopx.NewApi()
|
||||
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign returned error: %v", err)
|
||||
}
|
||||
|
||||
params["sign"] = sign
|
||||
err = api.Verify(context.Background(), "huangxinyun", params)
|
||||
if err != nil {
|
||||
t.Errorf("Verify returned error: %v", err)
|
||||
}
|
||||
|
||||
// 测试用例2: 签名参数不存在
|
||||
paramsWithoutSign := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
}
|
||||
|
||||
err = api.Verify(context.Background(), "huangxinyun", paramsWithoutSign)
|
||||
if err != bopx.ErrorSignParamNotExist {
|
||||
t.Errorf("Verify should return ErrorSignParamNotExist, got: %v", err)
|
||||
}
|
||||
|
||||
// 测试用例3: 签名参数不是字符串
|
||||
paramsWithInvalidSign := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
"sign": 12345, // 非字符串类型
|
||||
}
|
||||
|
||||
err = api.Verify(context.Background(), "huangxinyun", paramsWithInvalidSign)
|
||||
if err != bopx.ErrorSignMustBeString {
|
||||
t.Errorf("Verify should return ErrorSignMustBeString, got: %v", err)
|
||||
}
|
||||
|
||||
// 测试用例4: 签名不匹配
|
||||
paramsWithWrongSign := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
"sign": "WRONGSIGN",
|
||||
}
|
||||
|
||||
err = api.Verify(context.Background(), "huangxinyun", paramsWithWrongSign)
|
||||
if err != bopx.ErrorSignFail {
|
||||
t.Errorf("Verify should return ErrorSignFail, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestApiIgnoreKeys 测试忽略键功能
|
||||
func TestApiIgnoreKeys(t *testing.T) {
|
||||
params := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
"platform_key": "ignored",
|
||||
"sign": "ignored",
|
||||
"key": "ignored",
|
||||
}
|
||||
|
||||
api := bopx.NewApi(bopx.WithIgnoreKeys("platform_key", "sign", "key"))
|
||||
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign returned error: %v", err)
|
||||
}
|
||||
|
||||
// 验证忽略的键不影响签名结果
|
||||
paramsWithoutIgnored := map[string]interface{}{
|
||||
"name": "huang",
|
||||
"age": 18,
|
||||
}
|
||||
|
||||
signWithoutIgnored, err := api.GetSign(context.Background(), "huangxinyun", paramsWithoutIgnored)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign returned error: %v", err)
|
||||
}
|
||||
|
||||
if sign != signWithoutIgnored {
|
||||
t.Errorf("Signatures with/without ignored keys should be equal. With ignored: %s, without: %s", sign, signWithoutIgnored)
|
||||
}
|
||||
}
|
||||
|
||||
// TestApiEmptyParams 测试空参数
|
||||
func TestApiEmptyParams(t *testing.T) {
|
||||
params := map[string]interface{}{}
|
||||
|
||||
api := bopx.NewApi(bopx.WithIgnoreKeys("platform_key", "sign", "key"))
|
||||
sign, err := api.GetSign(context.Background(), "huangxinyun", params)
|
||||
|
||||
assert.NotNil(t, err)
|
||||
|
||||
assert.Equal(t, bopx.ErrorSignParamIsEmpty, err)
|
||||
assert.Equal(t, "", sign)
|
||||
|
||||
}
|
||||
|
||||
// TestApiSpecialValues 测试特殊值
|
||||
func TestApiSpecialValues(t *testing.T) {
|
||||
params := map[string]interface{}{
|
||||
"empty_string": "",
|
||||
"nil_value": nil,
|
||||
"zero": 0,
|
||||
"special_chars": "!@#$%^&*()_+-=[]{}|;':\",./<>?",
|
||||
}
|
||||
|
||||
api := bopx.NewApi(bopx.WithIgnoreKeys("platform_key", "sign", "key"))
|
||||
sign, err := api.GetSign(context.Background(), "testkey", params)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign returned error: %v", err)
|
||||
}
|
||||
|
||||
if sign == "" {
|
||||
t.Error("Sign should not be empty for special values")
|
||||
}
|
||||
|
||||
params["sign"] = sign
|
||||
err = api.Verify(context.Background(), "testkey", params)
|
||||
if err != nil {
|
||||
t.Errorf("Verify returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestApiConsistentResults 测试签名一致性
|
||||
func TestApiConsistentResults(t *testing.T) {
|
||||
params1 := map[string]interface{}{
|
||||
"c": "third",
|
||||
"a": "first",
|
||||
"b": "second",
|
||||
}
|
||||
|
||||
params2 := map[string]interface{}{
|
||||
"b": "second",
|
||||
"c": "third",
|
||||
"a": "first",
|
||||
}
|
||||
|
||||
api := bopx.NewApi()
|
||||
|
||||
sign1, err := api.GetSign(context.Background(), "consistentkey", params1)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign for params1 returned error: %v", err)
|
||||
}
|
||||
|
||||
sign2, err := api.GetSign(context.Background(), "consistentkey", params2)
|
||||
if err != nil {
|
||||
t.Errorf("GetSign for params2 returned error: %v", err)
|
||||
}
|
||||
|
||||
// 由于参数排序,两种不同顺序的map应该产生相同的签名
|
||||
if sign1 != sign2 {
|
||||
t.Errorf("Signatures should be consistent regardless of parameter order. sign1: %s, sign2: %s", sign1, sign2)
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,7 @@ var (
|
||||
ErrorSignParamNotExist = errors.New("签名参数不存在")
|
||||
ErrorSignMustBeString = errors.New("sign必须是字符串")
|
||||
ErrorSignFail = errors.New("验签失败")
|
||||
ErrorSignParamEmpty = errors.New("签名参数为空")
|
||||
ErrorSignParamIsEmpty = errors.New("签名参数不能为空")
|
||||
ErrorSignKeyIsEmpty = errors.New("签名key不能为空")
|
||||
)
|
||||
|
||||
@@ -2,4 +2,38 @@ module code.yun.ink/pkg/bopx
|
||||
|
||||
go 1.20
|
||||
|
||||
require code.yun.ink/pkg/convx v1.0.1
|
||||
require (
|
||||
code.yun.ink/pkg/convx v1.0.3
|
||||
github.com/stretchr/testify v1.8.3
|
||||
github.com/yuninks/loggerx v1.0.13
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.9.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,2 +1,89 @@
|
||||
code.yun.ink/pkg/convx v1.0.1 h1:T6yIVqyC1nQc9CO0C7iHn5rs7GxbaulmrJtxwg95q9Y=
|
||||
code.yun.ink/pkg/convx v1.0.1/go.mod h1:6xqmUend1kwarRvJ0TQlfzzS4QCWdRrXQiUY/ggzYqo=
|
||||
code.yun.ink/pkg/convx v1.0.3 h1:pH8dUOgsoaBYVQ3+4C2+uVua561nDxq6/GpaQ9wnCew=
|
||||
code.yun.ink/pkg/convx v1.0.3/go.mod h1:6xqmUend1kwarRvJ0TQlfzzS4QCWdRrXQiUY/ggzYqo=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/yuninks/loggerx v1.0.13 h1:NVb0oHoZeJ59ZAaU5HqcpY7TfZlLaXQEzkRhdOTthiA=
|
||||
github.com/yuninks/loggerx v1.0.13/go.mod h1:+QFoywQ1ICh4v40zj6OHM8GBZHEqV0yvRbkZjZUe2o4=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package bopx
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/yuninks/loggerx"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
logger loggerx.LoggerInterface // 日志接口
|
||||
ignoreKeys []string // 忽略签名的key
|
||||
}
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
func newOptions(opts ...Option) *Options {
|
||||
options := defaultOptions()
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func defaultOptions() *Options {
|
||||
return &Options{
|
||||
logger: loggerx.NewLogger(
|
||||
context.Background(),
|
||||
loggerx.SetEscapeHTML(false),
|
||||
),
|
||||
ignoreKeys: []string{
|
||||
"sign",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogger(logger loggerx.LoggerInterface) Option {
|
||||
return func(o *Options) {
|
||||
o.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func WithIgnoreKeys(keys ...string) Option {
|
||||
return func(o *Options) {
|
||||
o.ignoreKeys = keys
|
||||
}
|
||||
}
|
||||
+22
-14
@@ -2,28 +2,39 @@
|
||||
package bopx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"code.yun.ink/pkg/convx"
|
||||
"github.com/yuninks/loggerx"
|
||||
)
|
||||
|
||||
type platform struct {
|
||||
ingoreKey []string
|
||||
signKey string
|
||||
ingoreKeys []string
|
||||
logger loggerx.LoggerInterface
|
||||
}
|
||||
|
||||
func NewPlatform(ignoreKey []string, signKey string) *platform {
|
||||
func NewPlatform(opts ...Option) *platform {
|
||||
options := newOptions(opts...)
|
||||
return &platform{
|
||||
ingoreKey: ignoreKey,
|
||||
signKey: signKey,
|
||||
ingoreKeys: options.ignoreKeys,
|
||||
logger: options.logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *platform) GetSign(params map[string]interface{}) (sign string, err error) {
|
||||
for _, val := range l.ingoreKey {
|
||||
func (l *platform) GetSign(ctx context.Context, signKey string, params map[string]any) (sign string, err error) {
|
||||
|
||||
if signKey == "" {
|
||||
return "", ErrorSignKeyIsEmpty
|
||||
}
|
||||
if len(params) == 0 {
|
||||
return "", ErrorSignParamIsEmpty
|
||||
}
|
||||
|
||||
for _, val := range l.ingoreKeys {
|
||||
delete(params, val)
|
||||
}
|
||||
|
||||
@@ -40,13 +51,10 @@ func (l *platform) GetSign(params map[string]interface{}) (sign string, err erro
|
||||
if k > 0 {
|
||||
str = str + "&"
|
||||
}
|
||||
val, err := convx.ToString(params[v])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
val := convx.ToString(params[v])
|
||||
str = str + v + "=" + val
|
||||
}
|
||||
str = str + "&key=" + l.signKey
|
||||
str = str + "&key=" + signKey
|
||||
data := []byte(str)
|
||||
has := md5.Sum(data)
|
||||
md5str1 := fmt.Sprintf("%x", has) // []byte转16进制
|
||||
@@ -54,7 +62,7 @@ func (l *platform) GetSign(params map[string]interface{}) (sign string, err erro
|
||||
return sign, nil
|
||||
}
|
||||
|
||||
func (l *platform) VerifySign(params map[string]interface{}) error {
|
||||
func (l *platform) VerifySign(ctx context.Context, signKey string, params map[string]interface{}) error {
|
||||
sign, ok := params["sign"]
|
||||
if !ok {
|
||||
return ErrorSignParamNotExist
|
||||
@@ -63,7 +71,7 @@ func (l *platform) VerifySign(params map[string]interface{}) error {
|
||||
if !ok {
|
||||
return ErrorSignMustBeString
|
||||
}
|
||||
g_sign, err := l.GetSign(params)
|
||||
g_sign, err := l.GetSign(ctx, signKey, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
package bopx_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"code.yun.ink/pkg/bopx"
|
||||
@@ -16,14 +17,14 @@ func TestGetSign(t *testing.T) {
|
||||
// delete(params, "sign")
|
||||
// delete(params, "key")
|
||||
|
||||
s := bopx.NewPlatform([]string{"platform_key", "sign", "key"}, "huangxinyun")
|
||||
sign, err := s.GetSign(params)
|
||||
s := bopx.NewPlatform()
|
||||
sign, err := s.GetSign(context.Background(), "huangxinyun", params)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Log(sign)
|
||||
params["sign"] = sign
|
||||
err = s.VerifySign(params)
|
||||
err = s.VerifySign(context.Background(), "huangxinyun", params)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user