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)
+       })
+}

Reply via email to