@@ -22,12 +22,11 @@ import (
22
22
"errors"
23
23
"strings"
24
24
25
- "go.uber.org/zap"
26
-
27
25
api "github.com/polarismesh/polaris-server/common/api/v1"
28
26
"github.com/polarismesh/polaris-server/common/log"
29
27
"github.com/polarismesh/polaris-server/common/model"
30
28
"github.com/polarismesh/polaris-server/common/utils"
29
+ "go.uber.org/zap"
31
30
)
32
31
33
32
// IsOpenAuth 返回是否开启了操作鉴权
@@ -44,44 +43,43 @@ func (authMgn *defaultAuthChecker) IsOpenAuth() bool {
44
43
// step 3. 拉取token对应的操作者相关信息,注入到请求上下文中
45
44
// step 4. 进行权限检查
46
45
func (authMgn * defaultAuthChecker ) CheckPermission (authCtx * model.AcquireContext ) (bool , error ) {
47
- reqId := utils .ParseRequestID (authCtx .GetRequestContext ())
48
-
49
46
if ! authMgn .IsOpenAuth () {
50
47
return true , nil
51
48
}
52
49
53
- if err := authMgn .VerifyToken (authCtx ); err != nil {
54
- if errors .Is (err , model .ErrorTokenDisabled ) && authCtx .GetOperation () == model .Read {
55
- // 当前读操作不处理
56
- return true , nil
57
- }
50
+ reqId := utils .ParseRequestID (authCtx .GetRequestContext ())
51
+ if err := authMgn .VerifyCredential (authCtx ); err != nil {
58
52
return false , err
59
53
}
60
54
61
- // 开启鉴权之后,读操作需要一些鉴权上下文的信息,因此必须要先走完 verifytoken 才可以结束
62
55
if authCtx .GetOperation () == model .Read {
63
56
return true , nil
64
57
}
65
58
66
- tokenInfo := authCtx .GetAttachment ()[ model .TokenDetailInfoKey ].( TokenInfo )
67
- strategies , err := authMgn . findStrategies ( tokenInfo )
68
- // 如果访问的资源,其 owner 找不到对应的用户,则认为是可以被随意操作的资源
69
- noResourceNeedCheck := authMgn . removeNoStrategyResources ( authCtx )
59
+ operatorInfo := authCtx .GetAttachment (model .TokenDetailInfoKey ).( OperatorInfo )
60
+ if operatorInfo . Disable {
61
+ return false , model . ErrorTokenDisabled
62
+ }
70
63
64
+ strategies , err := authMgn .findStrategies (operatorInfo )
71
65
if err != nil {
72
66
log .AuthScope ().Error ("[Auth][Server] find strategies when check permission" , utils .ZapRequestID (reqId ),
73
- zap .Error (err ), zap .String ("token" , tokenInfo .String ()))
67
+ zap .Error (err ), zap .Any ("token" , operatorInfo .String ()))
74
68
return false , err
75
69
}
76
70
77
- authCtx .GetAttachment ()[ model .OperatorLinkStrategy ] = strategies
71
+ authCtx .SetAttachment ( model .OperatorLinkStrategy , strategies )
78
72
73
+ noResourceNeedCheck := authMgn .removeNoStrategyResources (authCtx )
79
74
if ! noResourceNeedCheck && len (strategies ) == 0 {
80
75
log .AuthScope ().Error ("[Auth][Server]" , utils .ZapRequestID (reqId ),
81
76
zap .String ("msg" , "need check resource is not empty, but strategies is empty" ))
82
- return false , errors .New (api . Code2Info ( api . NotAllowedAccess ) )
77
+ return false , errors .New ("need check resource is not empty, but strategies is empty" )
83
78
}
84
79
80
+ log .AuthScope ().Info ("[Auth][Server] check permission args" , zap .Any ("resources" , authCtx .GetAccessResources ()),
81
+ zap .Any ("strategies" , strategies ))
82
+
85
83
ok , err := authMgn .authPlugin .CheckPermission (authCtx , strategies )
86
84
if err != nil {
87
85
log .AuthScope ().Error ("[Auth][Server] check permission args" , utils .ZapRequestID (reqId ),
@@ -94,97 +92,137 @@ func (authMgn *defaultAuthChecker) CheckPermission(authCtx *model.AcquireContext
94
92
return ok , err
95
93
}
96
94
97
- // verifyToken 对 token 进行检查验证,并将 verify 过程中解析出的数据注入到 model.AcquireContext 中
95
+ func canDowngradeAnonymous (authCtx * model.AcquireContext , err error ) bool {
96
+ if authCtx .GetModule () == model .AuthModule {
97
+ return false
98
+ }
99
+
100
+ if AuthOption .Strict {
101
+ return false
102
+ }
103
+
104
+ if errors .Is (err , model .ErrorTokenInvalid ) {
105
+ return true
106
+ }
107
+ if errors .Is (err , model .ErrorTokenNotExist ) {
108
+ return true
109
+ }
110
+
111
+ return false
112
+ }
113
+
114
+ // VerifyCredential 对 token 进行检查验证,并将 verify 过程中解析出的数据注入到 model.AcquireContext 中
98
115
// step 1. 首先对 token 进行解析,获取相关的数据信息,注入到整个的 AcquireContext 中
99
116
// step 2. 最后对 token 进行一些验证步骤的执行
100
- func (authMgn * defaultAuthChecker ) VerifyToken (authCtx * model.AcquireContext ) error {
117
+ // step 3. 兜底措施:如果开启了鉴权的非严格模式,则根据错误的类型,判断是否转为匿名用户进行访问
118
+ // - 如果不是访问权限控制相关模块(用户、用户组、权限策略),不得转为匿名用户
119
+ func (authMgn * defaultAuthChecker ) VerifyCredential (authCtx * model.AcquireContext ) error {
101
120
if ! authMgn .IsOpenAuth () && authCtx .GetModule () != model .AuthModule {
102
121
return nil
103
122
}
104
123
105
- tokenInfo , err := authMgn .DecodeToken (authCtx .GetToken ())
106
- if err != nil {
107
- log .AuthScope ().Error ("[Auth][Server] decode token" , utils .ZapRequestIDByCtx (authCtx .GetRequestContext ()),
108
- zap .Error (err ))
109
- return err
110
- }
124
+ reqId := utils .ParseRequestID (authCtx .GetRequestContext ())
111
125
112
- ownerId , isOwner , err := authMgn .checkToken (& tokenInfo )
113
- if err != nil {
114
- log .AuthScope ().Error ("[Auth][Server] check token" , utils .ZapRequestIDByCtx (authCtx .GetRequestContext ()),
115
- zap .Error (err ))
116
- return err
126
+ checkErr := func () error {
127
+ operator , err := authMgn .decodeToken (authCtx .GetToken ())
128
+ if err != nil {
129
+ log .AuthScope ().Error ("[Auth][Server] decode token" , zap .Error (err ))
130
+ return model .ErrorTokenInvalid
131
+ }
132
+
133
+ ownerId , isOwner , err := authMgn .checkToken (& operator )
134
+ if err != nil {
135
+ log .AuthScope ().Error ("[Auth][Server] check token" , zap .Error (err ))
136
+ return err
137
+ }
138
+
139
+ operator .OwnerID = ownerId
140
+ ctx := authCtx .GetRequestContext ()
141
+ ctx = context .WithValue (ctx , utils .ContextIsOwnerKey , isOwner )
142
+ ctx = context .WithValue (ctx , utils .ContextUserIDKey , operator .OperatorID )
143
+ ctx = context .WithValue (ctx , utils .ContextOwnerIDKey , ownerId )
144
+ authCtx .SetRequestContext (ctx )
145
+ authMgn .parseOperatorInfo (operator , authCtx )
146
+ if operator .Disable {
147
+ log .AuthScope ().Warn ("[Auth][Server] token already disabled" , utils .ZapRequestID (reqId ),
148
+ zap .Any ("token" , operator .String ()))
149
+ }
150
+ return nil
151
+ }()
152
+
153
+ if checkErr != nil {
154
+ if ! canDowngradeAnonymous (authCtx , checkErr ) {
155
+ return checkErr
156
+ }
157
+ log .AuthScope ().Warn ("[Auth][Server] parse operator info, downgrade to anonymous" , utils .ZapRequestID (reqId ),
158
+ zap .Error (checkErr ))
159
+ // 操作者信息解析失败,降级为匿名用户
160
+ authCtx .SetAttachment (model .TokenDetailInfoKey , newAnonymous ())
117
161
}
118
162
163
+ return nil
164
+ }
165
+
166
+ func (authMgn * defaultAuthChecker ) parseOperatorInfo (operator OperatorInfo , authCtx * model.AcquireContext ) {
167
+
119
168
ctx := authCtx .GetRequestContext ()
120
169
121
- if tokenInfo .IsUserToken {
122
- user := authMgn .Cache ().User ().GetUserByID (tokenInfo .OperatorID )
123
- tokenInfo .Role = user .Type
170
+ if operator .IsUserToken {
171
+ user := authMgn .Cache ().User ().GetUserByID (operator .OperatorID )
172
+ operator .Role = user .Type
124
173
ctx = context .WithValue (ctx , utils .ContextUserRoleIDKey , user .Type )
125
174
}
126
175
127
- ctx = context .WithValue (ctx , utils .ContextIsOwnerKey , isOwner )
128
- ctx = context .WithValue (ctx , utils .ContextUserIDKey , tokenInfo .OperatorID )
129
- ctx = context .WithValue (ctx , utils .ContextOwnerIDKey , ownerId )
130
-
131
- authCtx .GetAttachment ()[model .OperatorRoleKey ] = tokenInfo .Role
132
- authCtx .GetAttachment ()[model .OperatorPrincipalType ] = func () model.PrincipalType {
133
- if tokenInfo .IsUserToken {
176
+ authCtx .SetAttachment (model .OperatorRoleKey , operator .Role )
177
+ authCtx .SetAttachment (model .OperatorPrincipalType , func () model.PrincipalType {
178
+ if operator .IsUserToken {
134
179
return model .PrincipalUser
135
180
}
136
181
return model .PrincipalGroup
137
- }()
138
- authCtx .GetAttachment ()[ model .OperatorIDKey ] = tokenInfo .OperatorID
139
- authCtx .GetAttachment ()[ model .OperatorOwnerKey ] = ownerId
140
- authCtx .GetAttachment ()[ model .TokenDetailInfoKey ] = tokenInfo
182
+ }())
183
+ authCtx .SetAttachment ( model .OperatorIDKey , operator .OperatorID )
184
+ authCtx .SetAttachment ( model .OperatorOwnerKey , operator )
185
+ authCtx .SetAttachment ( model .TokenDetailInfoKey , operator )
141
186
142
187
authCtx .SetRequestContext (ctx )
143
-
144
- if tokenInfo .Disable {
145
- log .AuthScope ().Error ("[Auth][Server] token already disabled" ,
146
- utils .ZapRequestIDByCtx (authCtx .GetRequestContext ()), zap .String ("token" , tokenInfo .String ()))
147
- return model .ErrorTokenDisabled
148
- }
149
- return nil
150
188
}
151
189
152
- // DecodeToken 解析 token 信息,如果 t == "",直接返回一个空对象
153
- func (authMgn * defaultAuthChecker ) DecodeToken (t string ) (TokenInfo , error ) {
190
+ // decodeToken 解析 token 信息,如果 t == "",直接返回一个空对象
191
+ func (authMgn * defaultAuthChecker ) decodeToken (t string ) (OperatorInfo , error ) {
154
192
if t == "" {
155
- return TokenInfo {}, nil
193
+ return OperatorInfo {}, model . ErrorTokenInvalid
156
194
}
157
195
158
196
ret , err := decryptMessage ([]byte (AuthOption .Salt ), t )
159
197
if err != nil {
160
- return TokenInfo {}, err
198
+ return OperatorInfo {}, err
161
199
}
162
200
tokenDetails := strings .Split (ret , TokenSplit )
163
201
if len (tokenDetails ) != 2 {
164
- return TokenInfo {}, model .ErrorTokenInvalid
202
+ return OperatorInfo {}, model .ErrorTokenInvalid
165
203
}
166
204
167
205
detail := strings .Split (tokenDetails [1 ], "/" )
168
206
if len (detail ) != 2 {
169
- return TokenInfo {}, model .ErrorTokenInvalid
207
+ return OperatorInfo {}, model .ErrorTokenInvalid
170
208
}
171
209
172
- tokenInfo := TokenInfo {
210
+ tokenInfo := OperatorInfo {
173
211
Origin : t ,
174
212
IsUserToken : detail [0 ] == model .TokenForUser ,
175
213
OperatorID : detail [1 ],
176
214
Role : model .UnknownUserRole ,
177
215
}
178
216
179
- log .AuthScope ().Info ("[Auth][Server] token detail" , zap .String ("info" , tokenInfo .String ()))
217
+ log .AuthScope ().Info ("[Auth][Server] token detail" , zap .Any ("info" , tokenInfo .String ()))
180
218
181
219
return tokenInfo , nil
182
220
}
183
221
184
222
// checkToken 对 token 进行检查,如果 token 是一个空,直接返回默认值,但是不返回错误
185
223
// return {owner-id} {is-owner} {error}
186
- func (authMgn * defaultAuthChecker ) checkToken (tokenInfo * TokenInfo ) (string , bool , error ) {
187
- if tokenInfo . IsEmpty ( ) {
224
+ func (authMgn * defaultAuthChecker ) checkToken (tokenInfo * OperatorInfo ) (string , bool , error ) {
225
+ if IsEmptyOperator ( * tokenInfo ) {
188
226
return "" , false , nil
189
227
}
190
228
@@ -244,12 +282,12 @@ func (authMgn *defaultAuthChecker) findStrategiesByUserID(userId string) []*mode
244
282
}
245
283
246
284
// findStrategies Inquire about TOKEN information, the actual all-associated authentication strategy
247
- func (authMgn * defaultAuthChecker ) findStrategies (tokenInfo TokenInfo ) ([]* model.StrategyDetail , error ) {
285
+ func (authMgn * defaultAuthChecker ) findStrategies (tokenInfo OperatorInfo ) ([]* model.StrategyDetail , error ) {
248
286
var (
249
287
strategies []* model.StrategyDetail
250
288
)
251
289
252
- if tokenInfo . IsEmpty ( ) {
290
+ if IsEmptyOperator ( tokenInfo ) {
253
291
return make ([]* model.StrategyDetail , 0 ), nil
254
292
}
255
293
@@ -317,7 +355,7 @@ func (authMgn *defaultAuthChecker) removeNoStrategyResources(authCtx *model.Acqu
317
355
}
318
356
319
357
if authCtx .GetModule () == model .ConfigModule {
320
- // 检查配置空间
358
+ // 检查配置
321
359
cfgRes := resources [api .ResourceType_ConfigGroups ]
322
360
newCfgRes := make ([]model.ResourceEntry , 0 )
323
361
for index := range cfgRes {
@@ -329,13 +367,13 @@ func (authMgn *defaultAuthChecker) removeNoStrategyResources(authCtx *model.Acqu
329
367
newAccessRes [api .ResourceType_ConfigGroups ] = newCfgRes
330
368
}
331
369
332
- log .AuthScope ().Info ("[Auth][Server] remove no link strategy resource " , utils .ZapRequestID (reqId ),
370
+ log .AuthScope ().Info ("[Auth][Server] remove no link strategy final result " , utils .ZapRequestID (reqId ),
333
371
zap .Any ("resource" , newAccessRes ))
334
372
335
373
authCtx .SetAccessResources (newAccessRes )
336
374
noResourceNeedCheck := authCtx .IsAccessResourceEmpty ()
337
375
if noResourceNeedCheck {
338
- log .AuthScope ().Info ("[Auth][Server]" , utils .ZapRequestID (reqId ),
376
+ log .AuthScope ().Debug ("[Auth][Server]" , utils .ZapRequestID (reqId ),
339
377
zap .String ("msg" , "need check permission resource is empty" ))
340
378
}
341
379
0 commit comments