You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
|
package auth
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/hmac"
|
|
|
|
|
"crypto/sha256"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// HMACAuth HMAC算法鉴权
|
|
|
|
|
type HMACAuth struct {
|
|
|
|
|
SecretKey []byte
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sign 对给定Body生成expires后失效的签名
|
|
|
|
|
func (auth HMACAuth) Sign(body string, expires int64) string {
|
|
|
|
|
h := hmac.New(sha256.New, auth.SecretKey)
|
|
|
|
|
expireTimeStamp := strconv.FormatInt(expires, 10)
|
|
|
|
|
_, err := io.WriteString(h, body+":"+expireTimeStamp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fmt.Sprintf("%x", h.Sum(nil)) + ":" + expireTimeStamp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check 对给定Body和Sign进行鉴权,包括对expires的检查
|
|
|
|
|
func (auth HMACAuth) Check(body string, sign string) error {
|
|
|
|
|
signSlice := strings.Split(sign, ":")
|
|
|
|
|
// 如果未携带expires字段
|
|
|
|
|
if signSlice[len(signSlice)-1] == "" {
|
|
|
|
|
return ErrAuthFailed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证是否过期
|
|
|
|
|
expires, err := strconv.ParseInt(signSlice[len(signSlice)-1], 10, 64)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return ErrAuthFailed.WithError(err)
|
|
|
|
|
}
|
|
|
|
|
// 如果签名过期
|
|
|
|
|
if expires < time.Now().Unix() && expires != 0 {
|
|
|
|
|
return ErrExpired
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证签名
|
|
|
|
|
if auth.Sign(body, expires) != sign {
|
|
|
|
|
return ErrAuthFailed
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|