This is an automated email from the ASF dual-hosted git repository.
littlecui pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git
The following commit(s) were added to refs/heads/dev by this push:
new 9c8ce411 [opt] add cache to the logic of auth to improve performance
in the scene of rbac (#1461)
9c8ce411 is described below
commit 9c8ce411d8b7802305b1bf9ab8e25006f2c4f503
Author: tornado-ssy <[email protected]>
AuthorDate: Mon Mar 25 22:12:35 2024 +0800
[opt] add cache to the logic of auth to improve performance in the scene of
rbac (#1461)
Co-authored-by: songshiyuan 00649746 <[email protected]>
---
go.mod | 2 +-
server/plugin/auth/buildin/buildin.go | 54 +++++++++++++++++++++++++++---
server/plugin/auth/buildin/buildin_test.go | 32 +++++++++++++++---
3 files changed, 77 insertions(+), 11 deletions(-)
diff --git a/go.mod b/go.mod
index 9877a7ee..351c55cf 100644
--- a/go.mod
+++ b/go.mod
@@ -73,6 +73,7 @@ require (
)
require (
+ github.com/form3tech-oss/jwt-go v3.2.3+incompatible
github.com/ghodss/yaml v1.0.0
github.com/go-chassis/go-chassis-extension/protocol/fiber4r
v0.0.0-20220825091211-99d5e9810fd7
)
@@ -99,7 +100,6 @@ require (
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21
// indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/emicklei/go-restful
v2.15.1-0.20220703112237-d9c71e118c95+incompatible // indirect
- github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/go-chassis/go-restful-swagger20
v1.0.4-0.20220704025524-9243cbee26b7 // indirect
github.com/go-chassis/sc-client v0.6.1-0.20220728072125-dacdd0c834bf //
indirect
diff --git a/server/plugin/auth/buildin/buildin.go
b/server/plugin/auth/buildin/buildin.go
index 21f2d045..b90a743b 100644
--- a/server/plugin/auth/buildin/buildin.go
+++ b/server/plugin/auth/buildin/buildin.go
@@ -19,10 +19,18 @@ package buildin
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"net/http"
"strings"
+ "time"
+
+ "github.com/form3tech-oss/jwt-go"
+ rbacmodel "github.com/go-chassis/cari/rbac"
+ "github.com/go-chassis/go-chassis/v2/security/authr"
+ "github.com/go-chassis/go-chassis/v2/server/restful"
+ "github.com/patrickmn/go-cache"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/apache/servicecomb-service-center/pkg/plugin"
@@ -32,12 +40,14 @@ import (
"github.com/apache/servicecomb-service-center/server/plugin/auth"
rbacsvc
"github.com/apache/servicecomb-service-center/server/service/rbac"
"github.com/apache/servicecomb-service-center/server/service/rbac/token"
- rbacmodel "github.com/go-chassis/cari/rbac"
- "github.com/go-chassis/go-chassis/v2/security/authr"
- "github.com/go-chassis/go-chassis/v2/server/restful"
)
var ErrNoRoles = errors.New("no role found in token")
+var tokenCache = cache.New(cacheDefaultExpireTime, cacheDefaultCleanUpTime)
+
+const cacheErrorItemExpTime = 5 * time.Minute
+const cacheDefaultExpireTime = 5 * time.Minute
+const cacheDefaultCleanUpTime = 10 * time.Minute
func init() {
plugin.RegisterPlugin(plugin.Plugin{Kind: auth.AUTH, Name: "buildin",
New: New})
@@ -152,6 +162,15 @@ func (ba *TokenAuthenticator) VerifyToken(req
*http.Request) (interface{}, error
if v == "" {
return nil, rbacmodel.NewError(rbacmodel.ErrNoAuthHeader, "")
}
+ claims, ok := tokenCache.Get(v)
+ if ok {
+ switch claimsVal := claims.(type) {
+ case error:
+ return nil, claimsVal
+ default:
+ return claimsVal, nil
+ }
+ }
s := strings.Split(v, " ")
if len(s) != 2 {
return nil, rbacmodel.ErrInvalidHeader
@@ -160,24 +179,49 @@ func (ba *TokenAuthenticator) VerifyToken(req
*http.Request) (interface{}, error
claims, err := authr.Authenticate(req.Context(), to)
if err != nil {
+ SetTokenToCache(tokenCache, v, err)
return nil, err
}
+ SetTokenToCache(tokenCache, v, claims)
token.WithRequest(req, to)
return claims, nil
}
+func SetTokenToCache(tokenCache *cache.Cache, rawToken string, claims
interface{}) {
+ switch claimsVal := claims.(type) {
+ case error:
+ tokenCache.Set(rawToken, claimsVal, cacheErrorItemExpTime)
+ case jwt.MapClaims:
+ var expr int64
+ switch exp := claimsVal["exp"].(type) {
+ case float64:
+ expr = int64(exp)
+ case json.Number:
+ expr, _ = exp.Int64()
+ default:
+ expr = time.Now().Add(cacheDefaultExpireTime).Unix()
+ }
+ expDur := time.Until(time.Unix(expr, 0))
+ if expDur > 0 {
+ tokenCache.Set(rawToken, claimsVal, expDur)
+ }
+ default:
+ return
+ }
+}
+
// this method decouple business code and perm checks
func checkPerm(roleList []string, req *http.Request) ([]map[string]string,
error) {
hasAdmin, normalRoles := filterRoles(roleList)
if hasAdmin {
return nil, nil
}
- //todo fast check for dev role
+ // todo fast check for dev role
targetResource := FromRequest(req)
if targetResource == nil {
return nil, errors.New("no valid resouce scope")
}
- //TODO add project
+ // TODO add project
project := req.URL.Query().Get(":project")
return rbacsvc.Allow(req.Context(), project, normalRoles,
targetResource)
}
diff --git a/server/plugin/auth/buildin/buildin_test.go
b/server/plugin/auth/buildin/buildin_test.go
index 1ae61898..fa2e146f 100644
--- a/server/plugin/auth/buildin/buildin_test.go
+++ b/server/plugin/auth/buildin/buildin_test.go
@@ -20,18 +20,18 @@ package buildin_test
// initialize
import (
"context"
+ "errors"
"net/http"
"net/http/httptest"
"os"
"testing"
+ "time"
+
+ "github.com/form3tech-oss/jwt-go"
+ "github.com/patrickmn/go-cache"
_ "github.com/apache/servicecomb-service-center/test"
- "github.com/apache/servicecomb-service-center/pkg/rest"
- "github.com/apache/servicecomb-service-center/pkg/util"
- "github.com/apache/servicecomb-service-center/server/config"
-
"github.com/apache/servicecomb-service-center/server/plugin/auth/buildin"
- rbacsvc
"github.com/apache/servicecomb-service-center/server/service/rbac"
beego "github.com/beego/beego/v2/server/web"
"github.com/go-chassis/cari/pkg/errsvc"
carirbac "github.com/go-chassis/cari/rbac"
@@ -41,6 +41,12 @@ import (
"github.com/go-chassis/go-chassis/v2/security/secret"
"github.com/go-chassis/go-chassis/v2/server/restful"
"github.com/stretchr/testify/assert"
+
+ "github.com/apache/servicecomb-service-center/pkg/rest"
+ "github.com/apache/servicecomb-service-center/pkg/util"
+ "github.com/apache/servicecomb-service-center/server/config"
+
"github.com/apache/servicecomb-service-center/server/plugin/auth/buildin"
+ rbacsvc
"github.com/apache/servicecomb-service-center/server/service/rbac"
)
func init() {
@@ -175,3 +181,19 @@ func TestTokenAuthenticator_Identify(t *testing.T) {
}
})
}
+
+func TestSetTokenToCache(t *testing.T) {
+ tokenCache1 := cache.New(5*time.Minute, 10*time.Minute)
+ rawToken1 := "**1"
+ rawToken2 := "**2"
+ deleta, _ := time.ParseDuration("10m")
+ claims := &jwt.MapClaims{"exp": float64(time.Now().Add(deleta).Unix())}
+ t.Run("test Cache", func(t *testing.T) {
+ buildin.SetTokenToCache(tokenCache1, rawToken1, claims)
+ buildin.SetTokenToCache(tokenCache1, rawToken2, errors.New("bad
token"))
+ res1, _ := tokenCache1.Get(rawToken1)
+ res2, _ := tokenCache1.Get(rawToken2)
+ assert.NotNil(t, res1)
+ assert.NotNil(t, res2)
+ })
+}