forked from Qihoo360/wayne
/
logged.go
123 lines (107 loc) · 3.05 KB
/
logged.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
package base
import (
"encoding/json"
"net/http"
"strings"
"github.com/dgrijalva/jwt-go"
rsakey "github.com/Qihoo360/wayne/src/backend/apikey"
"github.com/Qihoo360/wayne/src/backend/bus"
"github.com/Qihoo360/wayne/src/backend/bus/message"
"github.com/Qihoo360/wayne/src/backend/models"
"github.com/Qihoo360/wayne/src/backend/models/response/errors"
"github.com/Qihoo360/wayne/src/backend/util/hack"
"github.com/Qihoo360/wayne/src/backend/util/logs"
)
var (
PublishRequestMessageMethodFilter = []string{
"POST",
"PUT",
"DELETE",
"PATCH",
}
)
type LoggedInController struct {
ParamBuilderController
User *models.User
}
func (c *LoggedInController) Prepare() {
authString := c.Ctx.Input.Header("Authorization")
kv := strings.Split(authString, " ")
if len(kv) != 2 || kv[0] != "Bearer" {
logs.Error("AuthString invalid:", authString)
c.CustomAbort(http.StatusUnauthorized, "Token invalid!")
}
tokenString := kv[1]
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
// since we only use the one private key to sign the tokens,
// we also only use its public counter part to verify
return rsakey.RsaPublicKey, nil
})
errResult := errors.ErrorResult{}
switch err.(type) {
case nil: // no error
if !token.Valid { // but may still be invalid
errResult.Code = http.StatusUnauthorized
errResult.Msg = "Token Invalid ! "
}
case *jwt.ValidationError: // something was wrong during the validation
errResult.Code = http.StatusUnauthorized
errResult.Msg = err.Error()
default: // something else went wrong
errResult.Code = http.StatusInternalServerError
errResult.Msg = err.Error()
}
if err != nil {
c.CustomAbort(errResult.Code, errResult.Msg)
}
claim := token.Claims.(jwt.MapClaims)
aud := claim["aud"].(string)
c.User, err = models.UserModel.GetUserDetail(aud)
if err != nil {
c.CustomAbort(http.StatusInternalServerError, err.Error())
}
}
func (c *LoggedInController) publishRequestMessage(code int, data interface{}) {
var requestNeedAudit bool
for _, m := range PublishRequestMessageMethodFilter {
if c.Ctx.Request.Method == m {
requestNeedAudit = true
}
}
if !requestNeedAudit {
return
}
var err error
controller, method := c.GetControllerAndAction()
// 由于框架及项目抽象设计的问题,`data`作为interface类型多次传递,从Success/Error函数中传入的`data`可能的类型有:
// * string
// * nil
// * 实现MarshalJSON的任意结构
var body []byte
switch val := data.(type) {
case string:
body = hack.Slice(val)
default:
body, _ = json.Marshal(data)
}
messageData, err := json.Marshal(message.RequestMessageData{
URI: c.Ctx.Input.URI(),
Controller: controller,
Method: method,
User: c.User.Name,
IP: c.Ctx.Input.IP(),
ResponseStatus: code,
ResponseBody: body,
})
if err != nil {
logs.Error(err)
} else {
msg := message.Message{
Type: message.TypeRequest,
Data: json.RawMessage(messageData),
}
if err := bus.Notify(msg); err != nil {
logs.Error(err)
}
}
}