-
Notifications
You must be signed in to change notification settings - Fork 0
/
gin_enc_base.go
169 lines (157 loc) · 3.69 KB
/
gin_enc_base.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/**
gin 数据加密中间件
支持request请求加密、response响应数据加密
支持加密方式有
AES 对称加密
也可以自己实现 Encryptor 接口来自定义加密方式
request请求加密方式,将请求的json加密后,以表单的形式提交
enc=请求json加密信息
response响应数据加密,将返回的数据加密后返回
*/
package xlhttp
import (
"bytes"
"encoding/json"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"net/http"
"strings"
)
type EncRequest struct {
Enc string `json:"enc" form:"enc" binding:"required"`
}
type Encryptor interface {
Decrypt(source string) (string, error) //加密
Encrypt(dec string) (string, error) //解密
}
func NewEncryptRequestMiddleware(encryptor Encryptor, debug bool) gin.HandlerFunc {
return func(c *gin.Context) {
var (
data string
err error
req EncRequest
)
contentType := c.ContentType()
method := c.Request.Method
switch method {
case http.MethodPost:
switch {
case strings.Contains(contentType, gin.MIMEJSON):
err = c.ShouldBindBodyWith(&req, binding.JSON)
break
case strings.Contains(contentType, gin.MIMEPOSTForm),
strings.Contains(contentType, gin.MIMEPOSTForm):
err = c.ShouldBindWith(&req, binding.Form)
break
default:
err = c.ShouldBind(&req)
}
break
case http.MethodGet:
err = c.ShouldBindQuery(&req)
}
if err != nil && !debug {
c.AbortWithStatus(500)
return
}
enc := req.Enc
if len(enc) > 0 || !debug {
data, err = encryptor.Decrypt(enc)
if err != nil {
c.AbortWithStatus(500)
return
}
c.Request.Header.Set("Content-Type", gin.MIMEJSON)
c.Set(gin.BodyBytesKey, []byte(data))
}
c.Next()
}
}
type responseBodyWriter struct {
gin.ResponseWriter
Body *bytes.Buffer
}
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.Body.Write(b)
return len(b), nil
}
func NewEncryptResponseMiddleware(encryptor Encryptor) gin.HandlerFunc {
return func(c *gin.Context) {
w := &responseBodyWriter{Body: &bytes.Buffer{}, ResponseWriter: c.Writer}
c.Writer = w
c.Next()
// 处理请求
var response string
var err error
response = w.Body.String()
if len(response) > 0 {
response, err = encryptor.Encrypt(response)
if err != nil {
c.AbortWithStatus(500)
return
}
}
_, err = c.Writer.WriteString(response)
if err != nil {
c.AbortWithStatus(500)
return
}
}
}
func NewDataEncryptResponseMiddleware(encryptor Encryptor, debug bool) gin.HandlerFunc {
return func(c *gin.Context) {
w := &responseBodyWriter{Body: &bytes.Buffer{}, ResponseWriter: c.Writer}
c.Writer = w
c.Next()
// 处理请求
var (
obj JsonResponse
dataMap map[string]interface{}
dataJson, objJson []byte
response, encStr string
err error
)
response = w.Body.String()
// 加密封装
err = json.Unmarshal([]byte(response), &obj)
if err != nil {
c.AbortWithStatus(500)
return
}
if obj.Data != nil {
dataJson, err = json.Marshal(obj.Data)
}
if err != nil {
c.AbortWithStatus(500)
return
}
if len(dataJson) > 0 {
encStr, err = encryptor.Encrypt(string(dataJson))
if err != nil {
c.AbortWithStatus(500)
return
}
}
if debug {
if len(dataJson) > 0 {
err = json.Unmarshal(dataJson, &dataMap)
if err != nil {
c.AbortWithStatus(500)
return
}
}
}
if dataMap == nil {
dataMap = make(map[string]interface{})
}
dataMap["enc"] = encStr
obj.Data = dataMap
objJson, err = json.Marshal(obj)
_, err = c.Writer.WriteString(string(objJson))
c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8")
if err != nil {
c.AbortWithStatus(500)
return
}
}
}