This commit is contained in:
laodaming 2023-11-07 11:40:16 +08:00
parent 139c289f1d
commit e90af652ca

View File

@ -2,8 +2,13 @@ package logic
import ( import (
"context" "context"
"crypto/aes"
"crypto/cipher"
"crypto/sha256" "crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -53,20 +58,35 @@ func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) {
logx.Error("读取请求body失败", err) logx.Error("读取请求body失败", err)
return return
} }
defer r.Body.Close()
//计算签名 //计算签名
timestamp := r.Header.Get("X-Lark-Request-Timestamp") timestamp := r.Header.Get("X-Lark-Request-Timestamp")
nonce := r.Header.Get("X-Lark-Request-Nonce") nonce := r.Header.Get("X-Lark-Request-Nonce")
encryptKey := "DmiHQ2bHhKiR3KK4tIjLShbs13eErxKA" encryptKey := "DmiHQ2bHhKiR3KK4tIjLShbs13eErxKA"
signature := r.Header.Get("X-Lark-Signature") signature := r.Header.Get("X-Lark-Signature")
sign := l.calculateSignature(timestamp, nonce, encryptKey, bodyBytes) sign := l.CalculateFeiShuWebhookSignature(timestamp, nonce, encryptKey, bodyBytes)
if signature != sign { if signature != sign {
logx.Error("非法的消息,签名验证不通过", sign, "====", signature) logx.Error("非法的消息,签名验证不通过", sign, "====", signature)
return return
} }
defer r.Body.Close() var encryptMsg EncryptWebhookMsg
if err = json.Unmarshal(bodyBytes, &encryptMsg); err != nil {
logx.Error("反序列化body失败", err)
return
}
if encryptMsg.Encrypt == "" {
logx.Error("消息加密信息是空的")
return
}
//解密
realMsgBytes, err := l.DecryptFeiShuWebhookMsg(encryptMsg.Encrypt, encryptKey)
if err != nil {
logx.Error(err)
return
}
//如果只是验证http连接的消息 //如果只是验证http连接的消息
var webhookMsg WebhookMsg var webhookMsg WebhookMsg
if err = json.Unmarshal(bodyBytes, &webhookMsg); err != nil { if err = json.Unmarshal(realMsgBytes, &webhookMsg); err != nil {
logx.Error("反序列化请求body失败", err) logx.Error("反序列化请求body失败", err)
return return
} }
@ -79,7 +99,6 @@ func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) {
w.Write(b) w.Write(b)
return return
} }
headerByte, err := json.Marshal(webhookMsg.Header) headerByte, err := json.Marshal(webhookMsg.Header)
if err != nil { if err != nil {
logx.Error("序列化请求体header失败:", err) logx.Error("序列化请求体header失败:", err)
@ -111,7 +130,7 @@ func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) {
} }
// 计算签名 // 计算签名
func (l *WebhookLogic) calculateSignature(timestamp, nonce, encryptKey string, body []byte) string { func (l *WebhookLogic) CalculateFeiShuWebhookSignature(timestamp, nonce, encryptKey string, body []byte) string {
var b strings.Builder var b strings.Builder
b.WriteString(timestamp) b.WriteString(timestamp)
b.WriteString(nonce) b.WriteString(nonce)
@ -124,3 +143,42 @@ func (l *WebhookLogic) calculateSignature(timestamp, nonce, encryptKey string, b
sig := fmt.Sprintf("%x", bs) sig := fmt.Sprintf("%x", bs)
return sig return sig
} }
// 解密事件消息
func (l *WebhookLogic) DecryptFeiShuWebhookMsg(encrypt string, encryptKey string) ([]byte, error) {
h := sha256.New()
_, err := h.Write([]byte(encryptKey))
if err != nil {
return nil, err
}
key := hex.EncodeToString(h.Sum(nil))
buf, err := base64.StdEncoding.DecodeString(encrypt)
if err != nil {
return nil, fmt.Errorf("base64StdEncode Error[%v]", err)
}
if len(buf) < aes.BlockSize {
return nil, errors.New("cipher too short")
}
keyBs := sha256.Sum256([]byte(key))
block, err := aes.NewCipher(keyBs[:sha256.Size])
if err != nil {
return nil, fmt.Errorf("AESNewCipher Error[%v]", err)
}
iv := buf[:aes.BlockSize]
buf = buf[aes.BlockSize:]
// CBC mode always works in whole blocks.
if len(buf)%aes.BlockSize != 0 {
return nil, errors.New("ciphertext is not a multiple of the block size")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(buf, buf)
n := strings.Index(string(buf), "{")
if n == -1 {
n = 0
}
m := strings.LastIndex(string(buf), "}")
if m == -1 {
m = len(buf) - 1
}
return buf[n : m+1], nil
}