fix device decrypt flow and delete_account response stability
Build docker and publish / build (20.15.1) (push) Failing after 8m0s

This commit is contained in:
2026-03-04 01:36:45 -08:00
parent 8bdc8afea3
commit 82626dd749
7 changed files with 143 additions and 5 deletions
+60
View File
@@ -24,17 +24,28 @@ import (
const (
noWritten = -1
defaultStatus = http.StatusOK
ctxDeviceDecryptStatusKey = "device_decrypt_status"
ctxDeviceDecryptReasonKey = "device_decrypt_reason"
ctxEncryptedQueryKey = "encrypted_query"
ctxDecryptedQueryKey = "decrypted_query"
ctxEncryptedBodyKey = "encrypted_request_body"
ctxDecryptedBodyKey = "decrypted_request_body"
)
func DeviceMiddleware(srvCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
if !srvCtx.Config.Device.Enable {
c.Set(ctxDeviceDecryptStatusKey, "skipped")
c.Set(ctxDeviceDecryptReasonKey, "device_encryption_disabled")
c.Next()
return
}
if srvCtx.Config.Device.SecuritySecret == "" {
c.Set(ctxDeviceDecryptStatusKey, "failed")
c.Set(ctxDeviceDecryptReasonKey, "device_secret_empty")
result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.SecretIsEmpty), "Secret is empty"))
c.Abort()
return
@@ -48,12 +59,22 @@ func DeviceMiddleware(srvCtx *svc.ServiceContext) func(c *gin.Context) {
loginType, ok := ctx.Value(constant.CtxLoginType).(string)
if !ok || loginType != "device" {
c.Set(ctxDeviceDecryptStatusKey, "skipped")
if ok {
c.Set(ctxDeviceDecryptReasonKey, fmt.Sprintf("login_type_%s_not_device", loginType))
} else {
c.Set(ctxDeviceDecryptReasonKey, "login_type_not_found")
}
c.Next()
return
}
rw := NewResponseWriter(c, srvCtx)
if !rw.Decrypt() {
c.Set(ctxDeviceDecryptStatusKey, "failed")
if _, exists := c.Get(ctxDeviceDecryptReasonKey); !exists {
c.Set(ctxDeviceDecryptReasonKey, "decrypt_failed")
}
result.HttpResult(c, nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidCiphertext), "Invalid ciphertext"))
c.Abort()
return
@@ -112,13 +133,21 @@ func (rw *ResponseWriter) Encrypt() {
func (rw *ResponseWriter) Decrypt() bool {
if !rw.encryption {
rw.c.Set(ctxDeviceDecryptStatusKey, "skipped")
rw.c.Set(ctxDeviceDecryptReasonKey, "response_encryption_disabled")
return true
}
//判断url链接中是否存在data和iv数据,存在就进行解密并设置回去
query := rw.c.Request.URL.Query()
originalRawQuery := rw.c.Request.URL.RawQuery
dataStr := query.Get("data")
timeStr := query.Get("time")
hasEncryptedQuery := dataStr != "" && timeStr != ""
queryDecrypted := false
if hasEncryptedQuery {
rw.c.Set(ctxEncryptedQueryKey, originalRawQuery)
}
if dataStr != "" && timeStr != "" {
decrypt, err := pkgaes.Decrypt(dataStr, rw.encryptionKey, timeStr)
if err == nil {
@@ -132,42 +161,73 @@ func (rw *ResponseWriter) Decrypt() bool {
query.Del("time")
rw.c.Request.RequestURI = fmt.Sprintf("%s?%s", rw.c.Request.RequestURI[:strings.Index(rw.c.Request.RequestURI, "?")], query.Encode())
rw.c.Request.URL.RawQuery = query.Encode()
rw.c.Set(ctxDecryptedQueryKey, query.Encode())
queryDecrypted = true
}
} else {
rw.c.Set(ctxDeviceDecryptReasonKey, fmt.Sprintf("query_decrypt_failed:%v", err))
}
}
//判断body是否存在数据,存在就尝试解密,并设置回去
body, err := io.ReadAll(rw.c.Request.Body)
if err != nil {
if queryDecrypted {
rw.c.Set(ctxDeviceDecryptStatusKey, "success")
} else {
rw.c.Set(ctxDeviceDecryptStatusKey, "skipped")
}
rw.c.Set(ctxDeviceDecryptReasonKey, fmt.Sprintf("read_body_failed:%v", err))
return true
}
if len(body) == 0 {
if queryDecrypted {
rw.c.Set(ctxDeviceDecryptStatusKey, "success")
} else {
rw.c.Set(ctxDeviceDecryptStatusKey, "skipped")
if hasEncryptedQuery {
rw.c.Set(ctxDeviceDecryptReasonKey, "query_decrypt_failed")
} else {
rw.c.Set(ctxDeviceDecryptReasonKey, "empty_body")
}
}
return true
}
rw.c.Set(ctxEncryptedBodyKey, string(body))
params := map[string]interface{}{}
err = json.Unmarshal(body, &params)
data := params["data"]
nonce := params["time"]
if err != nil || data == nil {
if err != nil {
rw.c.Set(ctxDeviceDecryptReasonKey, fmt.Sprintf("body_unmarshal_failed:%v", err))
} else {
rw.c.Set(ctxDeviceDecryptReasonKey, "body_data_field_missing")
}
return false
}
str, ok := data.(string)
if !ok {
rw.c.Set(ctxDeviceDecryptReasonKey, "body_data_not_string")
return false
}
iv, ok := nonce.(string)
if !ok {
rw.c.Set(ctxDeviceDecryptReasonKey, "body_time_not_string")
return false
}
decrypt, err := pkgaes.Decrypt(str, rw.encryptionKey, iv)
if err != nil {
rw.c.Set(ctxDeviceDecryptReasonKey, fmt.Sprintf("body_decrypt_failed:%v", err))
return false
}
rw.c.Request.Body = io.NopCloser(bytes.NewBuffer([]byte(decrypt)))
rw.c.Set(ctxDecryptedBodyKey, decrypt)
rw.c.Set(ctxDeviceDecryptStatusKey, "success")
return true
}