本文内容

事件安全校验

WPS协作开放平台推送的事件消息,均会经过加密。应用接收到的消息体参数如下:

参数 参数类型 是否必带 说明
id string true 消息 id
topic string true 消息主题
operation string true 消息变更动作
time int64 true 时间(秒为单位的时间戳)
nonce string true iv 向量(解密时使用)
signature string true 消息签名
encrypted_data string true 消息变更的加密字段

应用需根据WPS协作官方提供的解密算法,对加密消息体进行解密,方可得到消息内容。

解密算法

消息解密示例(以 Golang 为例)

接收消息事件为例:

import (
    "encoding/json"
    "errors"
    "strconv"

    "github.com/gin-gonic/gin"
)

const (
    appId     = "xxxxxx"
    secretKey = "xxxxxxxxxx"
)

//收到的消息体
type Event struct {
    Topic         string `web:"topic"`
    Operation     string `web:"operation"`
    Time          int64  `web:"time"`
    Signature     string `web:"signature"`
    Nonce         string `web:"nonce"`
    EncryptedData string `web:"encrypted_data"`
}

//解密后的消息体
type MsgEventData struct {
    ChatId      int64       `json:"chat_id"`
    ChatType    uint8       `json:"chat_type"`
    CompanyId   int64       `json:"company_id"`
    Sender      *User       `json:"sender"`
    SendTime    int64       `json:"send_time"`
    MessageId   int64       `json:"message_id"`
    MessageType int64       `json:"message_type"`
    Content     interface{} `json:"content"`
    Mentions    []*User     `json:"mentions"`
}

type User struct {
    CompanyUid string `json:"company_uid"`
    CompanyId  string `json:"company_id"`
}

func openReceive(c *gin.Context) interface{} {
    event := &Event{}
    if err := c.ShouldBindJSON(event); err != nil {
        return err
    }

    content := appId + ":" + event.Topic + ":" + event.Nonce + ":" + strconv.FormatInt(event.Time, 10) + ":" + event.EncryptedData
    signature := HmacSha256(content, secretKey)
    if signature != event.Signature {
        return errors.New("Signature check faild")
    }

    cipher := Md5(secretKey)
    decryptData, err := Decrypt(event.EncryptedData, cipher, event.Nonce)
    if err != nil {
        return err
    }

    data := &MsgEventData{}
    err = json.Unmarshal([]byte(decryptData), data)
    if err != nil {
        return err
    }

    return nil
}
本文内容