/
http.go
128 lines (103 loc) · 3.12 KB
/
http.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
package auther
import (
"context"
"net/http"
"github.com/rs/xid"
"github.com/infraboard/mcube/app"
"github.com/infraboard/mcube/exception"
"github.com/infraboard/mcube/logger"
"github.com/infraboard/mcube/logger/zap"
httpb "github.com/infraboard/mcube/pb/http"
"github.com/infraboard/keyauth/apps/token"
"github.com/infraboard/keyauth/apps/user/types"
"github.com/infraboard/keyauth/common/header"
)
// NewInternalAuther 内部使用的auther
func NewHTTPAuther() *HTTPAuther {
return &HTTPAuther{
l: zap.L().Named("Http Interceptor"),
token: app.GetGrpcApp(token.AppName).(token.ServiceServer),
}
}
// internal todo
type HTTPAuther struct {
l logger.Logger
token token.ServiceServer
}
func (a *HTTPAuther) Auth(r *http.Request, entry httpb.Entry) (
authInfo interface{}, err error) {
var tk *token.Token
// 从请求中获取access token
acessToken := r.Header.Get(header.OAuthTokenHeader)
if entry.AuthEnable {
ctx := r.Context()
// 校验身份
tk, err = a.ValidateIdentity(ctx, acessToken)
if err != nil {
return nil, err
}
// namesapce检查
if entry.RequiredNamespace && tk.NamespaceId == "" {
return nil, exception.NewBadRequest("namespace required!")
}
// 权限检查
err = a.ValidatePermission(ctx, tk, entry)
if err != nil {
return nil, err
}
}
// 设置RequestID
if r.Header.Get(header.RequestIdHeader) == "" {
r.Header.Set(header.RequestIdHeader, xid.New().String())
}
return tk, nil
}
func (a *HTTPAuther) ValidateIdentity(ctx context.Context, accessToken string) (*token.Token, error) {
a.l.Debug("start token identity check ...")
if accessToken == "" {
return nil, exception.NewBadRequest("token required")
}
req := token.NewValidateTokenRequest()
req.AccessToken = accessToken
tk, err := a.token.ValidateToken(ctx, req)
if err != nil {
return nil, err
}
a.l.Debugf("token check ok, username: %s", tk.Account)
return tk, nil
}
func (a *HTTPAuther) ValidatePermission(ctx context.Context, tk *token.Token, e httpb.Entry) error {
if tk == nil {
return exception.NewUnauthorized("validate permission need token")
}
// 如果是不做权限校验, 超级管理员直接放行
if tk.UserType.IsIn(types.UserType_SUPPER) {
a.l.Debugf("[%s] supper admin skip permission check!", tk.Account)
return nil
}
// 检查是否是允许的类型
if len(e.Allow) > 0 {
a.l.Debugf("[%s] start check permission to keyauth ...", tk.Account)
if !e.IsAllow(tk.UserType) {
return exception.NewPermissionDeny("no permission, allow: %s, but current: %s", e.Allow, tk.UserType)
}
a.l.Debugf("[%s] permission check passed", tk.Account)
}
return nil
}
// func (a *HTTPAuther) ResponseHook(w http.ResponseWriter, r *http.Request, entry httpb.Entry) {
// ctx := httpctx.GetContext(r)
// tk := ctx.AuthInfo.(*token.Token)
// // 审计日志
// od := newOperateEventData(&entry, tk)
// hd := newEventHeaderFromHTTP(r)
// if entry.AuditLog {
// if err := SendOperateEvent(r.URL.String(), nil, hd, od); err != nil {
// a.l.Errorf("send operate event error, %s", err)
// }
// }
// }
// SetLogger todo
func (a *HTTPAuther) SetLogger(l logger.Logger) {
a.l = l
}