/
executor.go
149 lines (133 loc) · 3.98 KB
/
executor.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
package rsa_filter
import (
"crypto/rsa"
"fmt"
"github.com/eolinker/apinto/drivers"
"github.com/eolinker/apinto/utils"
"github.com/eolinker/eosc"
"github.com/eolinker/eosc/eocontext"
http_service "github.com/eolinker/eosc/eocontext/http-context"
)
var _ eocontext.IFilter = (*executor)(nil)
var _ http_service.HttpFilter = (*executor)(nil)
var _ eosc.IWorker = (*executor)(nil)
type executor struct {
drivers.WorkerBase
// 解密 + 签名
privateKey *rsa.PrivateKey
// 验签 + 加密
publicKey *rsa.PublicKey
requestSignHeader string
responseSignHeader string
}
func (e *executor) DoFilter(ctx eocontext.EoContext, next eocontext.IChain) (err error) {
return http_service.DoHttpFilter(e, ctx, next)
}
func (e *executor) DoHttpFilter(ctx http_service.IHttpContext, next eocontext.IChain) (err error) {
orgContentType := ctx.Request().Header().GetHeader("Origin-Content-Type")
if orgContentType == "" {
orgContentType = "application/json"
}
body, _ := ctx.Request().Body().RawBody()
signature := ctx.Request().Header().GetHeader(e.requestSignHeader)
// 解密
decrBody, err := decrypt(body, e.privateKey)
if err != nil {
err = fmt.Errorf("decrypt body error: %w", err)
ctx.Response().SetBody([]byte(err.Error()))
ctx.Response().SetStatus(403, "403")
return err
}
ctx.SetLabel("request_body", string(decrBody))
ctx.WithValue("request_body_complete", 1)
ctx.Request().Header().Headers().Set("Content-Type", orgContentType)
if signature != "" {
decodeSign, err := utils.B64Decode(signature)
if err != nil {
err = fmt.Errorf("base64 decode error: %w", err)
ctx.Response().SetBody([]byte(err.Error()))
ctx.Response().SetStatus(403, "403")
return err
}
// 验签
err = verify(body, decodeSign, e.publicKey)
if err != nil {
err = fmt.Errorf("verify signature error: %w", err)
ctx.Response().SetBody([]byte(err.Error()))
ctx.Response().SetStatus(403, "403")
return err
}
}
// 转发时传输明文
ctx.Proxy().Body().SetRaw(orgContentType, decrBody)
ctx.Proxy().Header().SetHeader("Content-Type", orgContentType)
if next != nil {
err = next.DoChain(ctx)
}
responseContentType := ctx.Response().GetHeader("Content-Type")
body = ctx.Response().GetBody()
// 加密
encBody, err := encrypt(body, e.publicKey)
if err != nil {
err = fmt.Errorf("encrypt body error: %w", err)
ctx.Response().SetBody([]byte(err.Error()))
ctx.Response().SetStatus(403, "403")
return
}
if e.responseSignHeader != "" {
responseSign, err := sign(encBody, e.privateKey)
if err != nil {
err = fmt.Errorf("sign body error: %w", err)
ctx.Response().SetBody([]byte(err.Error()))
ctx.Response().SetStatus(403, "403")
return err
}
ctx.Response().SetHeader(e.responseSignHeader, utils.B64Encode(responseSign))
}
ctx.Response().SetBody(encBody)
ctx.Response().SetHeader("Content-Type", "application/octet-stream")
ctx.Response().SetHeader("Origin-Content-Type", responseContentType)
return
}
func (e *executor) Destroy() {
return
}
func (e *executor) Start() error {
return nil
}
func (e *executor) Reset(conf interface{}, workers map[eosc.RequireId]eosc.IWorker) error {
return nil
}
func (e *executor) reset(conf *Config) error {
privateKey, publicKey := []byte(conf.PrivateKey), []byte(conf.PublicKey)
if conf.Format == "base64" {
var err error
privateKey, err = utils.B64Decode(conf.PrivateKey)
if err != nil {
return fmt.Errorf("descrypt private key error: %w", err)
}
publicKey, err = utils.B64Decode(conf.PublicKey)
if err != nil {
return fmt.Errorf("descrypt public key error: %w", err)
}
}
var err error
e.privateKey, err = parsePrivateKey(privateKey)
if err != nil {
return err
}
e.publicKey, err = parsePublicKey(publicKey)
if err != nil {
return err
}
e.requestSignHeader = conf.RequestSignHeader
e.responseSignHeader = conf.ResponseSignHeader
return nil
}
func (e *executor) Stop() error {
e.Destroy()
return nil
}
func (e *executor) CheckSkill(skill string) bool {
return http_service.FilterSkillName == skill
}