service/vendor/github.com/CatchZeng/dingtalk/internal/security/security.go

83 lines
2.0 KiB
Go
Raw Normal View History

2024-02-29 09:55:56 +08:00
package security
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"math"
"net/url"
"strconv"
"time"
)
// https://oapi.dingtalk.com/robot/send?access_token=xxx
const dingTalkOAPI = "oapi.dingtalk.com"
var dingTalkURL url.URL = url.URL{
Scheme: "https",
Host: dingTalkOAPI,
Path: "robot/send",
}
// URL get DingTalk URL with accessToken & secret
// If no signature is set, the secret is set to ""
// 如果没有加签secret 设置为 "" 即可
func URL(accessToken string, secret string) (string, error) {
timestamp := strconv.FormatInt(time.Now().Unix()*1000, 10)
return URLWithTimestamp(timestamp, accessToken, secret)
}
// URLWithTimestamp get DingTalk URL with timestamp & accessToken & secret
func URLWithTimestamp(timestamp string, accessToken string, secret string) (string, error) {
dtu := dingTalkURL
value := url.Values{}
value.Set("access_token", accessToken)
if secret == "" {
dtu.RawQuery = value.Encode()
return dtu.String(), nil
}
sign, err := sign(timestamp, secret)
if err != nil {
dtu.RawQuery = value.Encode()
return dtu.String(), err
}
value.Set("timestamp", timestamp)
value.Set("sign", sign)
dtu.RawQuery = value.Encode()
return dtu.String(), nil
}
// Validate validate
// https://ding-doc.dingtalk.com/doc#/serverapi2/elzz1p
func Validate(signStr, timestamp, secret string) (bool, error) {
t, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil {
return false, err
}
timeGap := time.Since(time.Unix(t, 0))
if math.Abs(timeGap.Hours()) > 1 {
return false, fmt.Errorf("specified timestamp is expired")
}
ourSign, err := sign(timestamp, secret)
if err != nil {
return false, err
}
return ourSign == signStr, nil
}
func sign(timestamp string, secret string) (string, error) {
stringToSign := fmt.Sprintf("%s\n%s", timestamp, secret)
h := hmac.New(sha256.New, []byte(secret))
if _, err := io.WriteString(h, stringToSign); err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
}