74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
|
package signature
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"crypto/hmac"
|
||
|
"crypto/sha256"
|
||
|
"encoding/base64"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"net/url"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"git.bvbej.com/bvbej/base-golang/pkg/time_parse"
|
||
|
)
|
||
|
|
||
|
func (s *signature) Verify(authorization, date string, path string, method string, params url.Values) (ok bool, err error) {
|
||
|
if date == "" {
|
||
|
err = errors.New("date required")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if path == "" {
|
||
|
err = errors.New("path required")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if method == "" {
|
||
|
err = errors.New("method required")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
methodName := strings.ToUpper(method)
|
||
|
if !methods[methodName] {
|
||
|
err = errors.New("method param error")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
ts, err := time_parse.ParseCSTInLocation(date)
|
||
|
if err != nil {
|
||
|
err = errors.New("date must follow '2006-01-02 15:04:05'")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if time_parse.SubInLocation(ts) > float64(s.ttl/time.Second) {
|
||
|
err = fmt.Errorf("date exceeds limit [%v]", s.ttl)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Encode() 方法中自带 sorted by key
|
||
|
sortParamsEncode, err := url.QueryUnescape(params.Encode())
|
||
|
if err != nil {
|
||
|
err = fmt.Errorf("url QueryUnescape error [%v]", err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
buffer := bytes.NewBuffer(nil)
|
||
|
buffer.WriteString(path)
|
||
|
buffer.WriteString(delimiter)
|
||
|
buffer.WriteString(methodName)
|
||
|
buffer.WriteString(delimiter)
|
||
|
buffer.WriteString(sortParamsEncode)
|
||
|
buffer.WriteString(delimiter)
|
||
|
buffer.WriteString(date)
|
||
|
|
||
|
// 对数据进行 hmac 加密,并进行 base64 encode
|
||
|
hash := hmac.New(sha256.New, []byte(s.secret))
|
||
|
hash.Write(buffer.Bytes())
|
||
|
digest := base64.StdEncoding.EncodeToString(hash.Sum(nil))
|
||
|
|
||
|
ok = authorization == fmt.Sprintf("%s %s", s.key, digest)
|
||
|
return
|
||
|
}
|