@@ -19,10 +19,18 @@ package buildin
19
19
20
20
import (
21
21
"context"
22
+ "encoding/json"
22
23
"errors"
23
24
"fmt"
24
25
"net/http"
25
26
"strings"
27
+ "time"
28
+
29
+ "github.com/form3tech-oss/jwt-go"
30
+ rbacmodel "github.com/go-chassis/cari/rbac"
31
+ "github.com/go-chassis/go-chassis/v2/security/authr"
32
+ "github.com/go-chassis/go-chassis/v2/server/restful"
33
+ "github.com/patrickmn/go-cache"
26
34
27
35
"github.com/apache/servicecomb-service-center/pkg/log"
28
36
"github.com/apache/servicecomb-service-center/pkg/plugin"
@@ -32,12 +40,14 @@ import (
32
40
"github.com/apache/servicecomb-service-center/server/plugin/auth"
33
41
rbacsvc "github.com/apache/servicecomb-service-center/server/service/rbac"
34
42
"github.com/apache/servicecomb-service-center/server/service/rbac/token"
35
- rbacmodel "github.com/go-chassis/cari/rbac"
36
- "github.com/go-chassis/go-chassis/v2/security/authr"
37
- "github.com/go-chassis/go-chassis/v2/server/restful"
38
43
)
39
44
40
45
var ErrNoRoles = errors .New ("no role found in token" )
46
+ var tokenCache = cache .New (cacheDefaultExpireTime , cacheDefaultCleanUpTime )
47
+
48
+ const cacheErrorItemExpTime = 5 * time .Minute
49
+ const cacheDefaultExpireTime = 5 * time .Minute
50
+ const cacheDefaultCleanUpTime = 10 * time .Minute
41
51
42
52
func init () {
43
53
plugin .RegisterPlugin (plugin.Plugin {Kind : auth .AUTH , Name : "buildin" , New : New })
@@ -152,6 +162,15 @@ func (ba *TokenAuthenticator) VerifyToken(req *http.Request) (interface{}, error
152
162
if v == "" {
153
163
return nil , rbacmodel .NewError (rbacmodel .ErrNoAuthHeader , "" )
154
164
}
165
+ claims , ok := tokenCache .Get (v )
166
+ if ok {
167
+ switch claimsVal := claims .(type ) {
168
+ case error :
169
+ return nil , claimsVal
170
+ default :
171
+ return claimsVal , nil
172
+ }
173
+ }
155
174
s := strings .Split (v , " " )
156
175
if len (s ) != 2 {
157
176
return nil , rbacmodel .ErrInvalidHeader
@@ -160,24 +179,49 @@ func (ba *TokenAuthenticator) VerifyToken(req *http.Request) (interface{}, error
160
179
161
180
claims , err := authr .Authenticate (req .Context (), to )
162
181
if err != nil {
182
+ SetTokenToCache (tokenCache , v , err )
163
183
return nil , err
164
184
}
185
+ SetTokenToCache (tokenCache , v , claims )
165
186
token .WithRequest (req , to )
166
187
return claims , nil
167
188
}
168
189
190
+ func SetTokenToCache (tokenCache * cache.Cache , rawToken string , claims interface {}) {
191
+ switch claimsVal := claims .(type ) {
192
+ case error :
193
+ tokenCache .Set (rawToken , claimsVal , cacheErrorItemExpTime )
194
+ case jwt.MapClaims :
195
+ var expr int64
196
+ switch exp := claimsVal ["exp" ].(type ) {
197
+ case float64 :
198
+ expr = int64 (exp )
199
+ case json.Number :
200
+ expr , _ = exp .Int64 ()
201
+ default :
202
+ expr = time .Now ().Add (cacheDefaultExpireTime ).Unix ()
203
+ }
204
+ expDur := time .Until (time .Unix (expr , 0 ))
205
+ if expDur > 0 {
206
+ tokenCache .Set (rawToken , claimsVal , expDur )
207
+ }
208
+ default :
209
+ return
210
+ }
211
+ }
212
+
169
213
// this method decouple business code and perm checks
170
214
func checkPerm (roleList []string , req * http.Request ) ([]map [string ]string , error ) {
171
215
hasAdmin , normalRoles := filterRoles (roleList )
172
216
if hasAdmin {
173
217
return nil , nil
174
218
}
175
- //todo fast check for dev role
219
+ // todo fast check for dev role
176
220
targetResource := FromRequest (req )
177
221
if targetResource == nil {
178
222
return nil , errors .New ("no valid resouce scope" )
179
223
}
180
- //TODO add project
224
+ // TODO add project
181
225
project := req .URL .Query ().Get (":project" )
182
226
return rbacsvc .Allow (req .Context (), project , normalRoles , targetResource )
183
227
}
0 commit comments