193 lines
5.0 KiB
Go
193 lines
5.0 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
zlog "github.com/rs/zerolog/log"
|
|
"gitlab.33.cn/chat/dtalk/pkg/address"
|
|
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
|
|
"gitlab.33.cn/chat/dtalk/pkg/util"
|
|
)
|
|
|
|
var log = zlog.Logger
|
|
|
|
func composeHttpResp(code int, msg string, data interface{}) interface{} {
|
|
type HttpAck struct {
|
|
Result int `json:"result"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data"`
|
|
}
|
|
var ret HttpAck
|
|
ret.Result = code
|
|
ret.Message = msg
|
|
ret.Data = data
|
|
return &ret
|
|
}
|
|
|
|
func parseRlt(result interface{}, err interface{}) (code int, msg string, data interface{}) {
|
|
if err != nil {
|
|
switch ty := err.(type) {
|
|
case *xerror.Error:
|
|
code = ty.Code()
|
|
msg = ty.Error()
|
|
data = ty.Data()
|
|
default:
|
|
log.Warn().Interface("err", err).Msg("inner error type")
|
|
e := xerror.NewError(xerror.CodeInnerError)
|
|
code = e.Code()
|
|
msg = e.Error()
|
|
data = err
|
|
}
|
|
return
|
|
}
|
|
|
|
code = xerror.CodeOK
|
|
if isNil(result) {
|
|
data = gin.H{}
|
|
} else {
|
|
data = result
|
|
}
|
|
return
|
|
}
|
|
|
|
func isNil(i interface{}) bool {
|
|
vi := reflect.ValueOf(i)
|
|
if vi.Kind() == reflect.Ptr {
|
|
return vi.IsNil()
|
|
}
|
|
return false
|
|
}
|
|
|
|
func RespMiddleWare() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
c.Next()
|
|
if v, ok := c.Get(RespMiddleWareDisabled); ok && v == true {
|
|
return
|
|
}
|
|
err := c.MustGet(ReqError)
|
|
result, _ := c.Get(ReqResult)
|
|
ret := composeHttpResp(parseRlt(result, err))
|
|
c.PureJSON(http.StatusOK, ret)
|
|
//c.PureJSON()
|
|
}
|
|
}
|
|
|
|
func AuthMiddleWare() gin.HandlerFunc {
|
|
return func(context *gin.Context) {
|
|
sig := context.GetHeader("FZM-SIGNATURE")
|
|
uuid := context.GetHeader("FZM-UUID")
|
|
device := context.GetHeader("FZM-DEVICE")
|
|
deviceName := context.GetHeader("FZM-DEVICE-NAME")
|
|
version := context.GetHeader("FZM-VERSION")
|
|
|
|
//
|
|
if sig == "MOCK" || sig == "MOCK2" {
|
|
mockAddr := ""
|
|
switch sig {
|
|
case "MOCK":
|
|
mockAddr = "1FKxgaEh5fuSm7a35BfUnKYAmradowpiTR"
|
|
case "MOCK2":
|
|
mockAddr = "1AsPsahP7FvpR7F2de1LhSB4SU5ShqZ7eu"
|
|
}
|
|
//set val
|
|
context.Set(Signature, sig)
|
|
context.Set(Address, mockAddr)
|
|
context.Set(Uuid, uuid)
|
|
context.Set(DeviceType, device)
|
|
context.Set(DeviceName, deviceName)
|
|
context.Set(Version, version)
|
|
} else {
|
|
pubKey, err := VerifyAddress(sig)
|
|
if err != nil {
|
|
log.Debug().Err(err).Msg("VerifyAddress failed")
|
|
context.Set(ReqError, err)
|
|
context.Abort()
|
|
return
|
|
}
|
|
addr := address.PublicKeyToAddress(address.NormalVer, pubKey)
|
|
if addr == "" {
|
|
log.Debug().Msg("PublicKeyToAddress addr is empty")
|
|
context.Set(ReqError, err)
|
|
context.Abort()
|
|
return
|
|
}
|
|
//set val
|
|
context.Set(Signature, sig)
|
|
context.Set(Address, addr)
|
|
context.Set(Uuid, uuid)
|
|
context.Set(DeviceType, device)
|
|
context.Set(DeviceName, deviceName)
|
|
context.Set(Version, version)
|
|
}
|
|
}
|
|
}
|
|
|
|
func HeaderMiddleWare() gin.HandlerFunc {
|
|
return func(context *gin.Context) {
|
|
uuid := context.GetHeader("FZM-UUID")
|
|
device := context.GetHeader("FZM-DEVICE")
|
|
deviceName := context.GetHeader("FZM-DEVICE-NAME")
|
|
version := context.GetHeader("FZM-VERSION")
|
|
|
|
//set val
|
|
context.Set(Uuid, uuid)
|
|
context.Set(DeviceType, device)
|
|
context.Set(DeviceName, deviceName)
|
|
context.Set(Version, version)
|
|
}
|
|
}
|
|
|
|
//get pubKey
|
|
func VerifyAddress(str string) ([]byte, error) {
|
|
//<signature>#<msg>#<address>; <>
|
|
ss := strings.SplitN(str, "#", -1)
|
|
if len(ss) < 3 {
|
|
log.Debug().Err(fmt.Errorf("need length:%v,got:%v", 3, len(ss))).Str("sig", str).Msg("split signature failed")
|
|
return nil, xerror.NewError(xerror.SignatureInvalid)
|
|
}
|
|
sigData := ss[0]
|
|
msgData := ss[1]
|
|
pubKeyData := ss[2]
|
|
|
|
msg := strings.SplitN(msgData, "*", -1)
|
|
if len(msg) < 2 {
|
|
log.Debug().Err(fmt.Errorf("need msg length:%v,got:%v", 2, len(ss))).Str("msgData", msgData).Msg("split msg data failed")
|
|
return nil, xerror.NewError(xerror.SignatureInvalid)
|
|
}
|
|
time, err := strconv.ParseInt(msg[0], 10, 64)
|
|
if err != nil {
|
|
log.Debug().Err(err).Str("datetime", msg[0]).Msg("ParseInt datetime failed")
|
|
return nil, xerror.NewError(xerror.SignatureInvalid)
|
|
}
|
|
//secp256
|
|
sig, err := base64.StdEncoding.DecodeString(sigData)
|
|
if err != nil {
|
|
log.Debug().Err(err).Str("sigData", sigData).Msg("base64 decode sig data failed")
|
|
return nil, xerror.NewError(xerror.SignatureInvalid)
|
|
}
|
|
pubKey, err := util.HexDecode(pubKeyData)
|
|
if err != nil {
|
|
log.Debug().Err(err).Str("pubKeyData", pubKeyData).Msg("hex decode pubKey failed")
|
|
return nil, xerror.NewError(xerror.SignatureInvalid)
|
|
}
|
|
msg256 := sha256.Sum256([]byte(msgData))
|
|
if !util.Secp256k1Verify(msg256[:], sig, pubKey) {
|
|
log.Debug().Err(err).Str("msgData", msgData).Bytes("sig", sig).Bytes("pubKey", pubKey).
|
|
Msg("Secp256k1Verify failed")
|
|
return nil, xerror.NewError(xerror.SignatureInvalid)
|
|
}
|
|
//检查时间是否过期
|
|
if util.CheckTimeOut(time, HeaderTimeOut) {
|
|
log.Debug().Err(err).Int64("time", time).Msg("verify timeout")
|
|
return nil, xerror.NewError(xerror.SignatureExpired)
|
|
}
|
|
return pubKey, nil
|
|
}
|