encrypted_params.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package middleware
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io"
  6. "mime/multipart"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. "github.com/0xJacky/Nginx-UI/internal/crypto"
  11. "github.com/gin-gonic/gin"
  12. "github.com/uozi-tech/cosy"
  13. )
  14. var (
  15. e = cosy.NewErrorScope("middleware")
  16. ErrInvalidRequestFormat = e.New(40000, "invalid request format")
  17. ErrDecryptionFailed = e.New(40001, "decryption failed")
  18. ErrFormParseFailed = e.New(40002, "form parse failed")
  19. )
  20. func EncryptedParams() gin.HandlerFunc {
  21. return func(c *gin.Context) {
  22. // read the encrypted payload
  23. var encryptedReq struct {
  24. EncryptedParams string `json:"encrypted_params"`
  25. }
  26. if err := c.ShouldBindJSON(&encryptedReq); err != nil {
  27. c.AbortWithStatusJSON(http.StatusBadRequest, ErrInvalidRequestFormat)
  28. return
  29. }
  30. // decrypt the parameters
  31. decryptedData, err := crypto.Decrypt(encryptedReq.EncryptedParams)
  32. if err != nil {
  33. c.AbortWithStatusJSON(http.StatusBadRequest, ErrDecryptionFailed)
  34. return
  35. }
  36. // replace request body with decrypted data
  37. newBody, _ := json.Marshal(decryptedData)
  38. c.Request.Body = io.NopCloser(bytes.NewReader(newBody))
  39. c.Request.ContentLength = int64(len(newBody))
  40. c.Next()
  41. }
  42. }
  43. // EncryptedForm handles multipart/form-data with encrypted fields while preserving file uploads
  44. func EncryptedForm() gin.HandlerFunc {
  45. return func(c *gin.Context) {
  46. // Only process if the content type is multipart/form-data
  47. if !strings.Contains(c.GetHeader("Content-Type"), "multipart/form-data") {
  48. c.Next()
  49. return
  50. }
  51. // Parse the multipart form
  52. if err := c.Request.ParseMultipartForm(512 << 20); err != nil { // 512MB max memory
  53. c.AbortWithStatusJSON(http.StatusBadRequest, ErrFormParseFailed)
  54. return
  55. }
  56. // Check if encrypted_params field exists
  57. encryptedParams := c.Request.FormValue("encrypted_params")
  58. if encryptedParams == "" {
  59. // No encryption, continue normally
  60. c.Next()
  61. return
  62. }
  63. // Decrypt the parameters
  64. params, err := crypto.Decrypt(encryptedParams)
  65. if err != nil {
  66. c.AbortWithStatusJSON(http.StatusBadRequest, ErrDecryptionFailed)
  67. return
  68. }
  69. // Create a new multipart form with the decrypted data
  70. newForm := &multipart.Form{
  71. Value: make(map[string][]string),
  72. File: c.Request.MultipartForm.File, // Keep original file uploads
  73. }
  74. // Add decrypted values to the new form
  75. for key, val := range params {
  76. strVal, ok := val.(string)
  77. if ok {
  78. newForm.Value[key] = []string{strVal}
  79. } else {
  80. // Handle other types if necessary
  81. jsonVal, _ := json.Marshal(val)
  82. newForm.Value[key] = []string{string(jsonVal)}
  83. }
  84. }
  85. // Also copy original non-encrypted form values (except encrypted_params)
  86. for key, vals := range c.Request.MultipartForm.Value {
  87. if key != "encrypted_params" && newForm.Value[key] == nil {
  88. newForm.Value[key] = vals
  89. }
  90. }
  91. // Replace the original form with our modified one
  92. c.Request.MultipartForm = newForm
  93. // Remove the encrypted_params field from the form
  94. delete(c.Request.MultipartForm.Value, "encrypted_params")
  95. // Reset ContentLength as form structure has changed
  96. c.Request.ContentLength = -1
  97. // Sync the form values to the request PostForm to ensure Gin can access them
  98. if c.Request.PostForm == nil {
  99. c.Request.PostForm = make(url.Values)
  100. }
  101. // Copy all values from MultipartForm to PostForm
  102. for k, v := range newForm.Value {
  103. c.Request.PostForm[k] = v
  104. }
  105. c.Next()
  106. }
  107. }