Pārlūkot izejas kodu

feat:优化token模块

Cheng Jian 2 gadi atpakaļ
vecāks
revīzija
06589bec1b

+ 0 - 591
gtoken/gtoken.go

@@ -1,591 +0,0 @@
-package gtoken
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"github.com/gogf/gf/v2/crypto/gaes"
-	"github.com/gogf/gf/v2/crypto/gmd5"
-	"github.com/gogf/gf/v2/encoding/gbase64"
-	"github.com/gogf/gf/v2/frame/g"
-	"github.com/gogf/gf/v2/net/ghttp"
-	"github.com/gogf/gf/v2/os/gtime"
-	"github.com/gogf/gf/v2/text/gstr"
-	"github.com/gogf/gf/v2/util/gconv"
-	"github.com/gogf/gf/v2/util/grand"
-	"net/http"
-	"strings"
-)
-
-var GFToken *GfToken
-
-// GfToken gtoken结构体
-type GfToken struct {
-	// GoFrame server name
-	ServerName string
-	// 缓存模式 1 gcache 2 gredis 默认1
-	CacheMode int8
-	// 缓存key
-	CacheKey string
-	// 超时时间 默认10天(毫秒)
-	Timeout int
-	// 缓存刷新时间 默认为超时时间的一半(毫秒)
-	MaxRefresh int
-	// Token分隔符
-	TokenDelimiter string
-	// Token加密key
-	EncryptKey []byte
-	// 认证失败中文提示
-	AuthFailMsg string
-	// 是否支持多端登录,默认false
-	MultiLogin bool
-	// 是否是全局认证,兼容历史版本,已废弃
-	GlobalMiddleware bool
-	// 中间件类型 1 GroupMiddleware 2 BindMiddleware  3 GlobalMiddleware
-	MiddlewareType uint
-
-	// 登录路径
-	LoginPath string
-	// 登录验证方法 return userKey 用户标识 如果userKey为空,结束执行
-	LoginBeforeFunc func(r *ghttp.Request) (string, interface{})
-	// 登录返回方法
-	LoginAfterFunc func(r *ghttp.Request, respData Resp)
-	// 登出地址
-	LogoutPath string
-	// 登出验证方法 return true 继续执行,否则结束执行
-	LogoutBeforeFunc func(r *ghttp.Request) bool
-	// 登出返回方法
-	LogoutAfterFunc func(r *ghttp.Request, respData Resp)
-
-	// 拦截地址
-	AuthPaths g.SliceStr
-	// 拦截排除地址
-	AuthExcludePaths g.SliceStr
-	// 认证验证方法 return true 继续执行,否则结束执行
-	AuthBeforeFunc func(r *ghttp.Request) bool
-	// 认证返回方法
-	AuthAfterFunc func(r *ghttp.Request, respData Resp)
-}
-
-// Login 登录
-func (m *GfToken) Login(r *ghttp.Request) {
-	userKey, data := m.LoginBeforeFunc(r)
-	if userKey == "" {
-		g.Log().Error(r.Context(), msgLog(MsgErrUserKeyEmpty))
-		return
-	}
-
-	if m.MultiLogin {
-		// 支持多端重复登录,返回相同token
-		userCacheResp := m.getToken(r.Context(), userKey)
-		if userCacheResp.Success() {
-			respToken := m.EncryptToken(r.Context(), userKey, userCacheResp.GetString(KeyUuid))
-			m.LoginAfterFunc(r, respToken)
-			return
-		}
-	}
-
-	// 生成token
-	respToken := m.genToken(r.Context(), userKey, data)
-	m.LoginAfterFunc(r, respToken)
-
-}
-
-// Logout 登出
-func (m *GfToken) Logout(r *ghttp.Request) {
-	if !m.LogoutBeforeFunc(r) {
-		return
-	}
-
-	// 获取请求token
-	respData := m.getRequestToken(r)
-	if respData.Success() {
-		// 删除token
-		m.RemoveToken(r.Context(), respData.DataString())
-	}
-
-	m.LogoutAfterFunc(r, respData)
-}
-
-// AuthMiddleware 认证拦截
-func (m *GfToken) authMiddleware(r *ghttp.Request) {
-	urlPath := r.URL.Path
-	if !m.AuthPath(r.Context(), urlPath) {
-		// 如果不需要认证,继续
-		r.Middleware.Next()
-		return
-	}
-
-	// 不需要认证,直接下一步
-	if !m.AuthBeforeFunc(r) {
-		r.Middleware.Next()
-		return
-	}
-
-	// 获取请求token
-	tokenResp := m.getRequestToken(r)
-	if tokenResp.Success() {
-		// 验证token
-		tokenResp = m.validToken(r.Context(), tokenResp.DataString())
-	}
-
-	m.AuthAfterFunc(r, tokenResp)
-}
-
-// GetTokenData 通过token获取对象
-func (m *GfToken) GetTokenData(r *ghttp.Request) Resp {
-	respData := m.getRequestToken(r)
-	if respData.Success() {
-		// 验证token
-		respData = m.validToken(r.Context(), respData.DataString())
-	}
-
-	return respData
-}
-
-// AuthPath 判断路径是否需要进行认证拦截
-// return true 需要认证
-func (m *GfToken) AuthPath(ctx context.Context, urlPath string) bool {
-	// 去除后斜杠
-	if strings.HasSuffix(urlPath, "/") {
-		urlPath = gstr.SubStr(urlPath, 0, len(urlPath)-1)
-	}
-	// 分组拦截,登录接口不拦截
-	if m.MiddlewareType == MiddlewareTypeGroup {
-		if (m.LoginPath != "" && gstr.HasSuffix(urlPath, m.LoginPath)) ||
-			(m.LogoutPath != "" && gstr.HasSuffix(urlPath, m.LogoutPath)) {
-			return false
-		}
-	}
-
-	// 全局处理,认证路径拦截处理
-	if m.MiddlewareType == MiddlewareTypeGlobal {
-		var authFlag bool
-		for _, authPath := range m.AuthPaths {
-			tmpPath := authPath
-			if strings.HasSuffix(tmpPath, "/*") {
-				tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-2)
-			}
-			if gstr.HasPrefix(urlPath, tmpPath) {
-				authFlag = true
-				break
-			}
-		}
-
-		if !authFlag {
-			// 拦截路径不匹配
-			return false
-		}
-	}
-
-	// 排除路径处理,到这里nextFlag为true
-	for _, excludePath := range m.AuthExcludePaths {
-		tmpPath := excludePath
-		// 前缀匹配
-		if strings.HasSuffix(tmpPath, "/*") {
-			tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-2)
-			if gstr.HasPrefix(urlPath, tmpPath) {
-				// 前缀匹配不拦截
-				return false
-			}
-		} else {
-			// 全路径匹配
-			if strings.HasSuffix(tmpPath, "/") {
-				tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-1)
-			}
-			if urlPath == tmpPath {
-				// 全路径匹配不拦截
-				return false
-			}
-		}
-	}
-
-	return true
-}
-
-// getRequestToken 返回请求Token
-func (m *GfToken) getRequestToken(r *ghttp.Request) Resp {
-	authHeader := r.Header.Get("Authorization")
-	if authHeader != "" {
-		parts := strings.SplitN(authHeader, " ", 2)
-		if !(len(parts) == 2 && parts[0] == "Bearer") {
-			g.Log().Warning(r.Context(), msgLog(MsgErrAuthHeader, authHeader))
-			return Unauthorized(fmt.Sprintf(MsgErrAuthHeader, authHeader), "")
-		} else if parts[1] == "" {
-			g.Log().Warning(r.Context(), msgLog(MsgErrAuthHeader, authHeader))
-			return Unauthorized(fmt.Sprintf(MsgErrAuthHeader, authHeader), "")
-		}
-
-		return Succ(parts[1])
-	}
-
-	authHeader = r.Get(KeyToken).String()
-	if authHeader == "" {
-		return Unauthorized(MsgErrTokenEmpty, "")
-	}
-	return Succ(authHeader)
-
-}
-
-// genToken 生成Token
-func (m *GfToken) genToken(ctx context.Context, userKey string, data interface{}) Resp {
-	token := m.EncryptToken(ctx, userKey, "")
-	if !token.Success() {
-		return token
-	}
-
-	cacheKey := m.CacheKey + userKey
-	userCache := g.Map{
-		KeyUserKey:     userKey,
-		KeyUuid:        token.GetString(KeyUuid),
-		KeyData:        data,
-		KeyCreateTime:  gtime.Now().TimestampMilli(),
-		KeyRefreshTime: gtime.Now().TimestampMilli() + gconv.Int64(m.MaxRefresh),
-	}
-
-	cacheResp := m.setCache(ctx, cacheKey, userCache)
-	if !cacheResp.Success() {
-		return cacheResp
-	}
-
-	return token
-}
-
-// validToken 验证Token
-func (m *GfToken) validToken(ctx context.Context, token string) Resp {
-	if token == "" {
-		return Unauthorized(MsgErrTokenEmpty, "")
-	}
-
-	decryptToken := m.DecryptToken(ctx, token)
-	if !decryptToken.Success() {
-		return decryptToken
-	}
-
-	userKey := decryptToken.GetString(KeyUserKey)
-	uuid := decryptToken.GetString(KeyUuid)
-
-	userCacheResp := m.getToken(ctx, userKey)
-	if !userCacheResp.Success() {
-		return userCacheResp
-	}
-
-	if uuid != userCacheResp.GetString(KeyUuid) {
-		g.Log().Debug(ctx, msgLog(MsgErrAuthUuid)+", decryptToken:"+decryptToken.Json()+" cacheValue:"+gconv.String(userCacheResp.Data))
-		return Unauthorized(MsgErrAuthUuid, "")
-	}
-
-	return userCacheResp
-}
-
-// getToken 通过userKey获取Token
-func (m *GfToken) getToken(ctx context.Context, userKey string) Resp {
-	cacheKey := m.CacheKey + userKey
-
-	userCacheResp := m.getCache(ctx, cacheKey)
-	if !userCacheResp.Success() {
-		return userCacheResp
-	}
-	userCache := gconv.Map(userCacheResp.Data)
-
-	nowTime := gtime.Now().TimestampMilli()
-	refreshTime := userCache[KeyRefreshTime]
-
-	// 需要进行缓存超时时间刷新
-	if gconv.Int64(refreshTime) == 0 || nowTime > gconv.Int64(refreshTime) {
-		userCache[KeyCreateTime] = gtime.Now().TimestampMilli()
-		userCache[KeyRefreshTime] = gtime.Now().TimestampMilli() + gconv.Int64(m.MaxRefresh)
-		return m.setCache(ctx, cacheKey, userCache)
-	}
-
-	return Succ(userCache)
-}
-
-// RemoveToken 删除Token
-func (m *GfToken) RemoveToken(ctx context.Context, token string) Resp {
-	decryptToken := m.DecryptToken(ctx, token)
-	if !decryptToken.Success() {
-		return decryptToken
-	}
-
-	cacheKey := m.CacheKey + decryptToken.GetString(KeyUserKey)
-	return m.removeCache(ctx, cacheKey)
-}
-
-// EncryptToken token加密方法
-func (m *GfToken) EncryptToken(ctx context.Context, userKey string, uuid string) Resp {
-	if userKey == "" {
-		return Fail(MsgErrUserKeyEmpty)
-	}
-
-	if uuid == "" {
-		// 重新生成uuid
-		newUuid, err := gmd5.Encrypt(grand.Letters(10))
-		if err != nil {
-			g.Log().Error(ctx, msgLog(MsgErrAuthUuid), err)
-			return Error(MsgErrAuthUuid)
-		}
-		uuid = newUuid
-	}
-
-	tokenStr := userKey + m.TokenDelimiter + uuid
-
-	token, err := gaes.Encrypt([]byte(tokenStr), m.EncryptKey)
-	if err != nil {
-		g.Log().Error(ctx, msgLog(MsgErrTokenEncrypt), tokenStr, err)
-		return Error(MsgErrTokenEncrypt)
-	}
-
-	return Succ(g.Map{
-		KeyUserKey: userKey,
-		KeyUuid:    uuid,
-		KeyToken:   gbase64.EncodeToString(token),
-	})
-}
-
-// DecryptToken token解密方法
-func (m *GfToken) DecryptToken(ctx context.Context, token string) Resp {
-	if token == "" {
-		return Fail(MsgErrTokenEmpty)
-	}
-
-	token64, err := gbase64.Decode([]byte(token))
-	if err != nil {
-		g.Log().Error(ctx, msgLog(MsgErrTokenDecode), token, err)
-		return Error(MsgErrTokenDecode)
-	}
-	decryptToken, err2 := gaes.Decrypt(token64, m.EncryptKey)
-	if err2 != nil {
-		g.Log().Error(ctx, msgLog(MsgErrTokenEncrypt), token, err2)
-		return Error(MsgErrTokenEncrypt)
-	}
-	tokenArray := gstr.Split(string(decryptToken), m.TokenDelimiter)
-	if len(tokenArray) < 2 {
-		g.Log().Error(ctx, msgLog(MsgErrTokenLen), token)
-		return Error(MsgErrTokenLen)
-	}
-
-	return Succ(g.Map{
-		KeyUserKey: tokenArray[0],
-		KeyUuid:    tokenArray[1],
-	})
-}
-
-// InitConfig 初始化配置信息
-func (m *GfToken) InitConfig() bool {
-	if m.CacheMode == 0 {
-		m.CacheMode = CacheModeCache
-	}
-
-	if m.CacheKey == "" {
-		m.CacheKey = DefaultCacheKey
-	}
-
-	if m.Timeout == 0 {
-		m.Timeout = DefaultTimeout
-	}
-
-	if m.MaxRefresh == 0 {
-		m.MaxRefresh = m.Timeout / 2
-	}
-
-	if m.TokenDelimiter == "" {
-		m.TokenDelimiter = DefaultTokenDelimiter
-	}
-
-	if len(m.EncryptKey) == 0 {
-		m.EncryptKey = []byte(DefaultEncryptKey)
-	}
-
-	if m.AuthFailMsg == "" {
-		m.AuthFailMsg = DefaultAuthFailMsg
-	}
-
-	// 设置中间件模式,未设置说明历史版本,通过GlobalMiddleware兼容
-	if m.MiddlewareType == 0 {
-		if m.GlobalMiddleware {
-			m.MiddlewareType = MiddlewareTypeGlobal
-		} else {
-			m.MiddlewareType = MiddlewareTypeBind
-		}
-	}
-
-	if m.LoginAfterFunc == nil {
-		m.LoginAfterFunc = func(r *ghttp.Request, respData Resp) {
-			if !respData.Success() {
-				r.Response.WriteJson(respData)
-			} else {
-				r.Response.WriteJson(Succ(g.Map{
-					KeyToken: respData.GetString(KeyToken),
-				}))
-			}
-		}
-	}
-
-	if m.LogoutBeforeFunc == nil {
-		m.LogoutBeforeFunc = func(r *ghttp.Request) bool {
-			return true
-		}
-	}
-
-	if m.LogoutAfterFunc == nil {
-		m.LogoutAfterFunc = func(r *ghttp.Request, respData Resp) {
-			if respData.Success() {
-				r.Response.WriteJson(Succ(MsgLogoutSucc))
-			} else {
-				r.Response.WriteJson(respData)
-			}
-		}
-	}
-
-	if m.AuthBeforeFunc == nil {
-		m.AuthBeforeFunc = func(r *ghttp.Request) bool {
-			// 静态页面不拦截
-			if r.IsFileRequest() {
-				return false
-			}
-
-			return true
-		}
-	}
-	if m.AuthAfterFunc == nil {
-		m.AuthAfterFunc = func(r *ghttp.Request, respData Resp) {
-			if respData.Success() {
-				r.Middleware.Next()
-			} else {
-				var params map[string]interface{}
-				if r.Method == http.MethodGet {
-					params = r.GetMap()
-				} else if r.Method == http.MethodPost {
-					params = r.GetMap()
-				} else {
-					r.Response.Writeln(MsgErrReqMethod)
-					return
-				}
-
-				no := gconv.String(gtime.TimestampMilli())
-
-				g.Log().Warning(r.Context(), fmt.Sprintf("[AUTH_%s][url:%s][params:%s][data:%s]",
-					no, r.URL.Path, params, respData.Json()))
-				respData.Msg = m.AuthFailMsg
-				r.Response.WriteJson(respData)
-				r.ExitAll()
-			}
-		}
-	}
-
-	return true
-}
-
-// Start 启动
-func (m *GfToken) Start() error {
-	if !m.InitConfig() {
-		return errors.New(MsgErrInitFail)
-	}
-
-	ctx := context.Background()
-	g.Log().Info(ctx, msgLog("[params:"+m.String()+"]start... "))
-
-	s := g.Server(m.ServerName)
-
-	// 缓存模式
-	if m.CacheMode > CacheModeFile {
-		g.Log().Error(ctx, msgLog(MsgErrNotSet, "CacheMode"))
-		return errors.New(fmt.Sprintf(MsgErrNotSet, "CacheMode"))
-	}
-
-	// 初始化文件缓存
-	if m.CacheMode == 3 {
-		m.initFileCache(ctx)
-	}
-
-	// 认证拦截器
-	if m.AuthPaths == nil {
-		g.Log().Error(ctx, msgLog(MsgErrNotSet, "AuthPaths"))
-		return errors.New(fmt.Sprintf(MsgErrNotSet, "AuthPaths"))
-	}
-
-	// 是否是全局拦截
-	if m.MiddlewareType == MiddlewareTypeGlobal {
-		s.BindMiddlewareDefault(m.authMiddleware)
-	} else {
-		for _, authPath := range m.AuthPaths {
-			tmpPath := authPath
-			if !strings.HasSuffix(authPath, "/*") {
-				tmpPath += "/*"
-			}
-			s.BindMiddleware(tmpPath, m.authMiddleware)
-		}
-	}
-
-	// 登录
-	if m.LoginPath == "" {
-		g.Log().Error(ctx, msgLog(MsgErrNotSet, "LoginPath"))
-		return errors.New(fmt.Sprintf(MsgErrNotSet, "LoginPath"))
-	}
-	if m.LoginBeforeFunc == nil {
-		g.Log().Error(ctx, msgLog(MsgErrNotSet, "LoginBeforeFunc"))
-		return errors.New(fmt.Sprintf(MsgErrNotSet, "LoginBeforeFunc"))
-	}
-	s.BindHandler(m.LoginPath, m.Login)
-
-	// 登出
-	if m.LogoutPath == "" {
-		g.Log().Error(ctx, msgLog(MsgErrNotSet, "LogoutPath"))
-		return errors.New(fmt.Sprintf(MsgErrNotSet, "LogoutPath"))
-	}
-	s.BindHandler(m.LogoutPath, m.Logout)
-
-	return nil
-}
-
-// Stop 结束
-func (m *GfToken) Stop(ctx context.Context) error {
-	g.Log().Info(ctx, "[GToken]stop. ")
-	return nil
-}
-
-// String token解密方法
-func (m *GfToken) String() string {
-	return gconv.String(g.Map{
-		// 缓存模式 1 gcache 2 gredis 默认1
-		"CacheMode":        m.CacheMode,
-		"CacheKey":         m.CacheKey,
-		"Timeout":          m.Timeout,
-		"TokenDelimiter":   m.TokenDelimiter,
-		"AuthFailMsg":      m.AuthFailMsg,
-		"MultiLogin":       m.MultiLogin,
-		"MiddlewareType":   m.MiddlewareType,
-		"LoginPath":        m.LoginPath,
-		"LogoutPath":       m.LogoutPath,
-		"AuthPaths":        gconv.String(m.AuthPaths),
-		"AuthExcludePaths": gconv.String(m.AuthExcludePaths),
-	})
-}
-
-// ValidToken 验证Token
-func (m *GfToken) ValidToken(ctx context.Context, token string) Resp {
-	if token == "" {
-		return Unauthorized(MsgErrTokenEmpty, "")
-	}
-
-	decryptToken := m.DecryptToken(ctx, token)
-	if !decryptToken.Success() {
-		return decryptToken
-	}
-
-	userKey := decryptToken.GetString(KeyUserKey)
-	uuid := decryptToken.GetString(KeyUuid)
-
-	userCacheResp := m.getToken(ctx, userKey)
-	if !userCacheResp.Success() {
-		return userCacheResp
-	}
-
-	if uuid != userCacheResp.GetString(KeyUuid) {
-		g.Log().Debug(ctx, msgLog(MsgErrAuthUuid)+", decryptToken:"+decryptToken.Json()+" cacheValue:"+gconv.String(userCacheResp.Data))
-		return Unauthorized(MsgErrAuthUuid, "")
-	}
-
-	return userCacheResp
-}

+ 0 - 54
gtoken/gtoken_group.go

@@ -1,54 +0,0 @@
-package gtoken
-
-import (
-	"context"
-	"errors"
-	"github.com/gogf/gf/v2/frame/g"
-	"github.com/gogf/gf/v2/net/ghttp"
-	"github.com/gogf/gf/v2/text/gstr"
-)
-
-// Middleware 绑定group
-func (m *GfToken) Middleware(ctx context.Context, group *ghttp.RouterGroup) error {
-	if !m.InitConfig() {
-		return errors.New("InitConfig fail")
-	}
-
-	// 设置为Group模式
-	m.MiddlewareType = MiddlewareTypeGroup
-	g.Log().Info(ctx, "[GToken][params:"+m.String()+"]start... ")
-
-	// 缓存模式
-	if m.CacheMode > CacheModeFile {
-		g.Log().Error(ctx, "[GToken]CacheMode set error")
-		return errors.New("CacheMode set error")
-	}
-	// 登录
-	if m.LoginPath == "" || m.LoginBeforeFunc == nil {
-		g.Log().Error(ctx, "[GToken]LoginPath or LoginBeforeFunc not set")
-		return errors.New("LoginPath or LoginBeforeFunc not set")
-	}
-	// 登出
-	if m.LogoutPath == "" {
-		g.Log().Error(ctx, "[GToken]LogoutPath not set")
-		return errors.New("LogoutPath not set")
-	}
-
-	group.Middleware(m.authMiddleware)
-
-	registerFunc(ctx, group, m.LoginPath, m.Login)
-	registerFunc(ctx, group, m.LogoutPath, m.Logout)
-
-	return nil
-}
-
-// 如果包含请求方式,按照请求方式注册;默认注册所有
-func registerFunc(ctx context.Context, group *ghttp.RouterGroup, pattern string, object interface{}) {
-	if gstr.Contains(pattern, ":") || gstr.Contains(pattern, "@") {
-		group.Map(map[string]interface{}{
-			pattern: object,
-		})
-	} else {
-		group.ALL(pattern, object)
-	}
-}

+ 0 - 14
gtoken/gtoken_msg_test.go

@@ -1,14 +0,0 @@
-package gtoken
-
-import (
-	"testing"
-)
-
-func TestMsg(t *testing.T) {
-	if msgLog("123") != "[GToken]123" {
-		t.Error("msg err")
-	}
-	if msgLog("123-%s-%d", "123", 44) != "[GToken]123-123-44" {
-		t.Error("msg sprintf err")
-	}
-}

+ 0 - 89
gtoken/gtoken_resp.go

@@ -1,89 +0,0 @@
-package gtoken
-
-import (
-	"encoding/json"
-	"github.com/gogf/gf/v2/container/gvar"
-	"github.com/gogf/gf/v2/util/gconv"
-)
-
-const (
-	SUCCESS      = 0
-	FAIL         = -1
-	ERROR        = -99
-	UNAUTHORIZED = -401
-)
-
-type Resp struct {
-	Code int         `json:"code"`
-	Msg  string      `json:"msg"`
-	Data interface{} `json:"data"`
-}
-
-// Success 获取Data值转字符串
-func (resp Resp) Success() bool {
-	return resp.Code == SUCCESS
-}
-
-// DataString 获取Data转字符串
-func (resp Resp) DataString() string {
-	return gconv.String(resp.Data)
-}
-
-// DataInt 获取Data转Int
-func (resp Resp) DataInt() int {
-	return gconv.Int(resp.Data)
-}
-
-// GetString 获取Data值转字符串
-func (resp Resp) GetString(key string) string {
-	return gconv.String(resp.Get(key))
-}
-
-// GetInt 获取Data值转Int
-func (resp Resp) GetInt(key string) int {
-	return gconv.Int(resp.Get(key))
-}
-
-// Get 获取Data值
-func (resp Resp) Get(key string) *gvar.Var {
-	m := gconv.Map(resp.Data)
-	if m == nil {
-		return nil
-	}
-	return gvar.New(m[key])
-}
-
-func (resp Resp) Json() string {
-	str, _ := json.Marshal(resp)
-	return string(str)
-}
-
-// Succ 成功
-func Succ(data interface{}) Resp {
-	return Resp{SUCCESS, "success", data}
-}
-
-// Fail 失败
-func Fail(msg string) Resp {
-	return Resp{FAIL, msg, ""}
-}
-
-// FailData 失败设置Data
-func FailData(msg string, data interface{}) Resp {
-	return Resp{FAIL, msg, data}
-}
-
-// Error 错误
-func Error(msg string) Resp {
-	return Resp{ERROR, msg, ""}
-}
-
-// ErrorData 错误设置Data
-func ErrorData(msg string, data interface{}) Resp {
-	return Resp{ERROR, msg, data}
-}
-
-// Unauthorized 认证失败
-func Unauthorized(msg string, data interface{}) Resp {
-	return Resp{UNAUTHORIZED, msg, data}
-}

+ 0 - 227
gtoken/gtoken_test.go

@@ -1,227 +0,0 @@
-package gtoken_test
-
-import (
-	"context"
-	"dashoo.cn/micro_libary/gtoken"
-	"github.com/gogf/gf/v2/frame/g"
-	"testing"
-)
-
-func TestAuthPathGlobal(t *testing.T) {
-	ctx := context.Background()
-
-	t.Log("Global auth path test ")
-	// 启动gtoken
-	gfToken := &gtoken.GfToken{
-		//Timeout:         10 * 1000,
-		AuthPaths:        g.SliceStr{"/user", "/system"},             // 这里是按照前缀拦截,拦截/user /user/list /user/add ...
-		AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/*"}, // 不拦截路径  /user/info,/system/user/info,/system/user,
-		MiddlewareType:   gtoken.MiddlewareTypeGlobal,                // 开启全局拦截
-	}
-
-	authPath(gfToken, t)
-	flag := gfToken.AuthPath(ctx, "/test")
-	if flag {
-		t.Error("error:", "/test auth path error")
-	}
-
-}
-
-func TestBindAuthPath(t *testing.T) {
-	t.Log("Bind auth path test ")
-	// 启动gtoken
-	gfToken := &gtoken.GfToken{
-		//Timeout:         10 * 1000,
-		AuthPaths:        g.SliceStr{"/user", "/system"},             // 这里是按照前缀拦截,拦截/user /user/list /user/add ...
-		AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/*"}, // 不拦截路径  /user/info,/system/user/info,/system/user,
-		MiddlewareType:   gtoken.MiddlewareTypeBind,                  // 开启局部拦截
-	}
-
-	authPath(gfToken, t)
-}
-
-func TestGroupAuthPath(t *testing.T) {
-	ctx := context.Background()
-
-	t.Log("Group auth path test ")
-	// 启动gtoken
-	gfToken := &gtoken.GfToken{
-		//Timeout:         10 * 1000,
-		AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/*"}, // 不拦截路径  /user/info,/system/user/info,/system/user,
-		LoginPath:        "/login",                                   // 登录路径
-		MiddlewareType:   gtoken.MiddlewareTypeGroup,                 // 开启组拦截
-	}
-
-	flag := gfToken.AuthPath(ctx, "/login")
-	if flag {
-		t.Error("error:", "/login auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/user/info")
-	if flag {
-		t.Error("error:", "/user/info auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/system/user/info")
-	if flag {
-		t.Error("error:", "/system/user/info auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/system/test")
-	if !flag {
-		t.Error("error:", "/system/test auth path error")
-	}
-}
-
-func TestAuthPathNoExclude(t *testing.T) {
-	ctx := context.Background()
-
-	t.Log("auth no exclude path test ")
-	// 启动gtoken
-	gfToken := &gtoken.GfToken{
-		//Timeout:         10 * 1000,
-		AuthPaths:      g.SliceStr{"/user", "/system"}, // 这里是按照前缀拦截,拦截/user /user/list /user/add ...
-		MiddlewareType: gtoken.MiddlewareTypeGlobal,    // 关闭全局拦截
-	}
-
-	authFlag := gfToken.AuthPath
-	if authFlag(ctx, "/test") {
-		t.Error(ctx, "error:", "/test auth path error")
-	}
-	if !authFlag(ctx, "/system/dept") {
-		t.Error(ctx, "error:", "/system/dept auth path error")
-	}
-
-	if !authFlag(ctx, "/user/info") {
-		t.Error(ctx, "error:", "/user/info auth path error")
-	}
-
-	if !authFlag(ctx, "/system/user") {
-		t.Error(ctx, "error:", "/system/user auth path error")
-	}
-}
-
-func TestAuthPathExclude(t *testing.T) {
-	ctx := context.Background()
-
-	t.Log("auth path test ")
-	// 启动gtoken
-	gfToken := &gtoken.GfToken{
-		//Timeout:         10 * 1000,
-		AuthPaths:        g.SliceStr{"/*"},                           // 这里是按照前缀拦截,拦截/user /user/list /user/add ...
-		AuthExcludePaths: g.SliceStr{"/user/info", "/system/user/*"}, // 不拦截路径  /user/info,/system/user/info,/system/user,
-		MiddlewareType:   gtoken.MiddlewareTypeGlobal,                // 开启全局拦截
-	}
-
-	authFlag := gfToken.AuthPath
-	if !authFlag(ctx, "/test") {
-		t.Error("error:", "/test auth path error")
-	}
-	if !authFlag(ctx, "//system/dept") {
-		t.Error("error:", "/system/dept auth path error")
-	}
-
-	if authFlag(ctx, "/user/info") {
-		t.Error("error:", "/user/info auth path error")
-	}
-
-	if authFlag(ctx, "/system/user") {
-		t.Error("error:", "/system/user auth path error")
-	}
-
-	if authFlag(ctx, "/system/user/info") {
-		t.Error("error:", "/system/user/info auth path error")
-	}
-
-}
-
-func authPath(gfToken *gtoken.GfToken, t *testing.T) {
-	ctx := context.Background()
-
-	flag := gfToken.AuthPath(ctx, "/user/info")
-	if flag {
-		t.Error("error:", "/user/info auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/system/user")
-	if flag {
-		t.Error("error:", "/system/user auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/system/user/info")
-	if flag {
-		t.Error("error:", "/system/user/info auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/system/dept")
-	if !flag {
-		t.Error("error:", "/system/dept auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/user/list")
-	if !flag {
-		t.Error("error:", "/user/list auth path error")
-	}
-
-	flag = gfToken.AuthPath(ctx, "/user/add")
-	if !flag {
-		t.Error("error:", "/user/add auth path error")
-	}
-}
-
-func TestEncryptDecryptToken(t *testing.T) {
-	t.Log("encrypt and decrypt token test ")
-	ctx := context.Background()
-
-	gfToken := gtoken.GfToken{}
-	gfToken.InitConfig()
-
-	userKey := "123123"
-	token := gfToken.EncryptToken(ctx, userKey, "")
-	if !token.Success() {
-		t.Error(token.Json())
-	}
-	t.Log(token.DataString())
-
-	token2 := gfToken.DecryptToken(ctx, token.GetString("token"))
-	if !token2.Success() {
-		t.Error(token2.Json())
-	}
-	t.Log(token2.DataString())
-	if userKey != token2.GetString("userKey") {
-		t.Error("error:", "token decrypt userKey error")
-	}
-	if token.GetString("uuid") != token2.GetString("uuid") {
-		t.Error("error:", "token decrypt uuid error")
-	}
-
-}
-
-func BenchmarkEncryptDecryptToken(b *testing.B) {
-	b.Log("encrypt and decrypt token test ")
-
-	ctx := context.Background()
-	gfToken := gtoken.GfToken{}
-	gfToken.InitConfig()
-
-	userKey := "123123"
-	token := gfToken.EncryptToken(ctx, userKey, "")
-	if !token.Success() {
-		b.Error(token.Json())
-	}
-	b.Log(token.DataString())
-
-	for i := 0; i < b.N; i++ {
-		token2 := gfToken.DecryptToken(ctx, token.GetString("token"))
-		if !token2.Success() {
-			b.Error(token2.Json())
-		}
-		b.Log(token2.DataString())
-		if userKey != token2.GetString("userKey") {
-			b.Error("error:", "token decrypt userKey error")
-		}
-		if token.GetString("uuid") != token2.GetString("uuid") {
-			b.Error("error:", "token decrypt uuid error")
-		}
-	}
-}

+ 6 - 6
micro/response.go

@@ -20,35 +20,35 @@ type Response struct {
 }
 
 // Succ 成功
-func (resp Response) SuccNil() {
+func (resp *Response) SuccNil() {
 	resp.Succ("")
 }
 
 // Succ 成功
-func (resp Response) Succ(data any) {
+func (resp *Response) Succ(data any) {
 	resp.Code = SUCCESS
 	resp.Message = "success"
 	resp.Data = data
 }
 
 // IsSuccess 获取Data值转字符串
-func (resp Response) IsSuccess() bool {
+func (resp *Response) IsSuccess() bool {
 	return resp.Code == SUCCESS
 }
 
 // String 获取Data转字符串
-func (resp Response) String() string {
+func (resp *Response) String() string {
 	return gconv.String(resp.Data)
 }
 
 // Json 获取Data转JSON格式
-func (resp Response) Json() string {
+func (resp *Response) Json() string {
 	str, _ := json.Marshal(resp)
 	return string(str)
 }
 
 // Get 获取Data值
-func (resp Response) Get(key string) *gvar.Var {
+func (resp *Response) Get(key string) *gvar.Var {
 	m := gconv.Map(resp.Data)
 	if m == nil {
 		return nil

+ 15 - 0
micro/rpcx_request_plugin.go

@@ -0,0 +1,15 @@
+package micro
+
+import (
+	"context"
+	"fmt"
+	"github.com/smallnest/rpcx/protocol"
+)
+
+type RpcxRequestPlugin struct {
+}
+
+func (plugin RpcxRequestPlugin) PostReadRequest(ctx context.Context, r *protocol.Message, e error) error {
+	fmt.Println(111111)
+	return nil
+}

+ 91 - 97
micro/server.go

@@ -2,17 +2,11 @@ package micro
 
 import (
 	"context"
-	"dashoo.cn/micro_libary/gtoken"
-	"github.com/gogf/gf/v2/errors/gerror"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/os/gctx"
-	"github.com/gogf/gf/v2/text/gstr"
 	"github.com/rcrowley/go-metrics"
 	"github.com/rpcxio/rpcx-consul/serverplugin"
-	"github.com/smallnest/rpcx/protocol"
 	"github.com/smallnest/rpcx/server"
-	"github.com/smallnest/rpcx/share"
-	"strings"
 	"time"
 )
 
@@ -51,94 +45,94 @@ func addConsulRegistryPlugin(ctx context.Context, s *server.Server, basePath, sr
 	s.Plugins.Add(r)
 }
 
-// HandleAuth 处理身份验证
-func HandleAuth(ctx context.Context, req *protocol.Message, token string, authExcludePaths []string) error {
-	tenant := getTenant(req)
-	g.Log().Infof(ctx, " ServicePath: %s, ServiceMethod: %s,Tenant:%s", req.ServicePath, req.ServiceMethod, tenant)
-
-	reqPath := "/" + req.ServicePath + "/" + req.ServiceMethod
-	if authPath(reqPath, authExcludePaths) {
-		req.Metadata["authExclude"] = "false"
-		var rsp gtoken.Resp
-		notAuthSrv := ctx.Value("NotAuthSrv")
-		if notAuthSrv != nil && notAuthSrv.(bool) {
-			rsp = gtoken.GFToken.ValidToken(ctx, token)
-		} else {
-			ctx = context.WithValue(ctx, share.ReqMetaDataKey, map[string]string{"tenant": tenant})
-			rsp = validToken(ctx, token)
-		}
-
-		if rsp.Code != 0 && rsp.Code != 200 {
-			return gerror.New("Token 认证失败!")
-		}
-		if req.Metadata != nil {
-			req.Metadata["userInfo"] = rsp.DataString()
-		}
-		return nil
-	}
-	return nil
-}
-
-// 判断路径是否需要进行认证拦截
-// return true 需要认证
-func authPath(urlPath string, authExcludePaths []string) bool {
-	// 去除后斜杠
-	if strings.HasSuffix(urlPath, "/") {
-		urlPath = gstr.SubStr(urlPath, 0, len(urlPath)-1)
-	}
-
-	// 排除路径处理,到这里nextFlag为true
-	for _, excludePath := range authExcludePaths {
-		tmpPath := excludePath
-		// 前缀匹配
-		if strings.HasSuffix(tmpPath, "/*") {
-			tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-2)
-			if gstr.HasPrefix(urlPath, tmpPath) {
-				// 前缀匹配不拦截
-				return false
-			}
-		} else {
-			// 全路径匹配
-			if strings.HasSuffix(tmpPath, "/") {
-				tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-1)
-			}
-			if urlPath == tmpPath {
-				// 全路径匹配不拦截
-				return false
-			}
-		}
-	}
-	return true
-}
-
-// 验证token
-func validToken(ctx context.Context, token string) gtoken.Resp {
-	grsp := gtoken.Resp{}
-	if token == "" {
-		grsp.Code = 401
-		grsp.Msg = "valid token empty"
-		return grsp
-	}
-
-	authService := InitMicroSrvClient(ctx, "Auth", "micro_srv.auth")
-	defer authService.Close()
-	rsp := &gtoken.Resp{}
-	err := authService.Call(ctx, "ValidToken", token, rsp)
-	if err != nil {
-		g.Log().Error(ctx, err)
-		grsp.Code = 401
-		return grsp
-	}
-	grsp.Code = int(rsp.Code)
-	grsp.Msg = rsp.Msg
-	grsp.Data = rsp.Data
-	return grsp
-}
-
-func getTenant(msg *protocol.Message) string {
-	var tenant string
-	if msg.Metadata != nil {
-		tenant = msg.Metadata[Tenant]
-	}
-	return tenant
-}
+//// HandleAuth 处理身份验证
+//func HandleAuth(ctx context.Context, req *protocol.Message, token string, authExcludePaths []string) error {
+//	tenant := getTenant(req)
+//	g.Log().Infof(ctx, " ServicePath: %s, ServiceMethod: %s,Tenant:%s", req.ServicePath, req.ServiceMethod, tenant)
+//
+//	reqPath := "/" + req.ServicePath + "/" + req.ServiceMethod
+//	if authPath(reqPath, authExcludePaths) {
+//		req.Metadata["authExclude"] = "false"
+//		var rsp gtoken.Resp
+//		notAuthSrv := ctx.Value("NotAuthSrv")
+//		if notAuthSrv != nil && notAuthSrv.(bool) {
+//			rsp = gtoken.GFToken.ValidToken(ctx, token)
+//		} else {
+//			ctx = context.WithValue(ctx, share.ReqMetaDataKey, map[string]string{"tenant": tenant})
+//			rsp = validToken(ctx, token)
+//		}
+//
+//		if rsp.Code != 0 && rsp.Code != 200 {
+//			return gerror.New("Token 认证失败!")
+//		}
+//		if req.Metadata != nil {
+//			req.Metadata["userInfo"] = rsp.DataString()
+//		}
+//		return nil
+//	}
+//	return nil
+//}
+//
+//// 判断路径是否需要进行认证拦截
+//// return true 需要认证
+//func authPath(urlPath string, authExcludePaths []string) bool {
+//	// 去除后斜杠
+//	if strings.HasSuffix(urlPath, "/") {
+//		urlPath = gstr.SubStr(urlPath, 0, len(urlPath)-1)
+//	}
+//
+//	// 排除路径处理,到这里nextFlag为true
+//	for _, excludePath := range authExcludePaths {
+//		tmpPath := excludePath
+//		// 前缀匹配
+//		if strings.HasSuffix(tmpPath, "/*") {
+//			tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-2)
+//			if gstr.HasPrefix(urlPath, tmpPath) {
+//				// 前缀匹配不拦截
+//				return false
+//			}
+//		} else {
+//			// 全路径匹配
+//			if strings.HasSuffix(tmpPath, "/") {
+//				tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-1)
+//			}
+//			if urlPath == tmpPath {
+//				// 全路径匹配不拦截
+//				return false
+//			}
+//		}
+//	}
+//	return true
+//}
+//
+//// 验证token
+//func validToken(ctx context.Context, token string) gtoken.Resp {
+//	grsp := gtoken.Resp{}
+//	if token == "" {
+//		grsp.Code = 401
+//		grsp.Msg = "valid token empty"
+//		return grsp
+//	}
+//
+//	authService := InitMicroSrvClient(ctx, "Auth", "micro_srv.auth")
+//	defer authService.Close()
+//	rsp := &gtoken.Resp{}
+//	err := authService.Call(ctx, "ValidToken", token, rsp)
+//	if err != nil {
+//		g.Log().Error(ctx, err)
+//		grsp.Code = 401
+//		return grsp
+//	}
+//	grsp.Code = int(rsp.Code)
+//	grsp.Msg = rsp.Msg
+//	grsp.Data = rsp.Data
+//	return grsp
+//}
+//
+//func getTenant(msg *protocol.Message) string {
+//	var tenant string
+//	if msg.Metadata != nil {
+//		tenant = msg.Metadata[Tenant]
+//	}
+//	return tenant
+//}

+ 305 - 0
token/token.go

@@ -0,0 +1,305 @@
+package token
+
+import (
+	"context"
+	"dashoo.cn/micro_libary/micro"
+	"fmt"
+	"github.com/gogf/gf/v2/crypto/gaes"
+	"github.com/gogf/gf/v2/crypto/gmd5"
+	"github.com/gogf/gf/v2/encoding/gbase64"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gctx"
+	"github.com/gogf/gf/v2/os/gtime"
+	"github.com/gogf/gf/v2/text/gstr"
+	"github.com/gogf/gf/v2/util/gconv"
+	"github.com/gogf/gf/v2/util/grand"
+	"github.com/smallnest/rpcx/protocol"
+	"strings"
+)
+
+// RpcxToken 结构体
+type RpcxToken struct {
+	// 缓存模式 1 gcache 2 gredis 默认1
+	CacheMode int64
+	// 缓存key
+	CacheKey string
+	// 超时时间 默认10天(毫秒)
+	Timeout int64
+	// 缓存刷新时间 默认为超时时间的一半(毫秒)
+	MaxRefresh int64
+	// Token分隔符
+	TokenDelimiter string
+	// Token加密key
+	EncryptKey []byte
+	// 认证失败中文提示
+	AuthFailMsg string
+	// 是否支持多端登录,默认false
+	MultiLogin bool
+	// 中间件类型 1 GroupMiddleware 2 BindMiddleware  3 GlobalMiddleware
+	MiddlewareType int64
+
+	// 拦截地址
+	AuthPaths []string
+	// 拦截排除地址
+	AuthExcludePaths []string
+	// 认证验证方法 return true 继续执行,否则结束执行
+	AuthBeforeFunc func(req *protocol.Message) bool
+	// 认证返回方法
+	AuthAfterFunc func(req *protocol.Message, resp micro.Response)
+}
+
+func NewRpcxToken() *RpcxToken {
+	m := new(RpcxToken)
+	ctx := gctx.New()
+	cacheMode, err := g.Config().Get(ctx, "token.cache-mode")
+	if err != nil || cacheMode.Int64() == 0 {
+		m.CacheMode = CacheModeCache
+	} else {
+		m.CacheMode = cacheMode.Int64()
+	}
+
+	cacheKey, err := g.Config().Get(ctx, "token.cache-key")
+	if err != nil || cacheKey.String() == "" {
+		m.CacheKey = DefaultCacheKey
+	} else {
+		m.CacheKey = cacheKey.String()
+	}
+
+	timeout, err := g.Config().Get(ctx, "token.timeout")
+	if err != nil || timeout.Int64() == 0 {
+		m.Timeout = DefaultTimeout
+	} else {
+		m.Timeout = timeout.Int64()
+	}
+
+	maxRefresh, err := g.Config().Get(ctx, "token.max-refresh")
+	if err != nil || maxRefresh.Int64() == 0 {
+		m.MaxRefresh = m.Timeout / 2
+	} else {
+		m.MaxRefresh = maxRefresh.Int64()
+	}
+
+	tokenDelimiter, err := g.Config().Get(ctx, "token.token-delimiter")
+	if err != nil || tokenDelimiter.String() == "" {
+		m.TokenDelimiter = DefaultTokenDelimiter
+	} else {
+		m.TokenDelimiter = tokenDelimiter.String()
+	}
+
+	encryptKey, err := g.Config().Get(ctx, "token.encrypt-key")
+	if err != nil || len(encryptKey.String()) == 0 {
+		m.EncryptKey = []byte(DefaultEncryptKey)
+	} else {
+		m.EncryptKey = []byte(encryptKey.String())
+	}
+	authFailMsg, err := g.Config().Get(ctx, "token.auth-fail-msg")
+	if err != nil || authFailMsg.String() == "" {
+		m.AuthFailMsg = DefaultAuthFailMsg
+	} else {
+		m.AuthFailMsg = authFailMsg.String()
+	}
+
+	multiLogin, err := g.Config().Get(ctx, "token.multi-login")
+	if err != nil || multiLogin.String() == "" {
+		m.MultiLogin = false
+	} else {
+		m.MultiLogin = authFailMsg.Bool()
+	}
+
+	return m
+}
+
+// GenToken 生成Token
+func (m *RpcxToken) GenToken(ctx context.Context, userKey string, data interface{}) *micro.Response {
+	token := m.EncryptToken(ctx, userKey, "")
+	if !token.IsSuccess() {
+		return token
+	}
+
+	cacheKey := m.CacheKey + userKey
+	userCache := g.Map{
+		KeyUserKey:     userKey,
+		KeyUuid:        token.Get(KeyUuid).String(),
+		KeyData:        data,
+		KeyCreateTime:  gtime.Now().TimestampMilli(),
+		KeyRefreshTime: gtime.Now().TimestampMilli() + gconv.Int64(m.MaxRefresh),
+	}
+
+	cacheResp := m.setCache(ctx, cacheKey, userCache)
+	if !cacheResp.IsSuccess() {
+		return cacheResp
+	}
+
+	return token
+}
+
+// GetTokenData 通过token获取对象
+func (m *RpcxToken) GetTokenData(ctx context.Context, req *protocol.Message) *micro.Response {
+	respData := m.GetRequestToken(ctx, req)
+	if respData.IsSuccess() {
+		// 验证token
+		respData = m.validToken(ctx, respData.String())
+	}
+
+	return respData
+}
+
+// getRequestToken 返回请求Token
+func (m *RpcxToken) GetRequestToken(ctx context.Context, req *protocol.Message) *micro.Response {
+	authHeader := req.Metadata["Authorization"]
+	if authHeader != "" {
+		parts := strings.SplitN(authHeader, " ", 2)
+		if !(len(parts) == 2 && parts[0] == "Bearer") {
+			g.Log().Warning(ctx, msgLog(MsgErrAuthHeader, authHeader))
+			return micro.Unauthorized(fmt.Sprintf(MsgErrAuthHeader, authHeader), "")
+		} else if parts[1] == "" {
+			g.Log().Warning(ctx, msgLog(MsgErrAuthHeader, authHeader))
+			return micro.Unauthorized(fmt.Sprintf(MsgErrAuthHeader, authHeader), "")
+		}
+
+		return micro.Success(parts[1])
+	}
+
+	authHeader = req.Metadata[KeyToken]
+	if authHeader == "" {
+		return micro.Unauthorized(MsgErrTokenEmpty, "")
+	}
+	return micro.Success(authHeader)
+
+}
+
+// validToken 验证Token
+func (m *RpcxToken) validToken(ctx context.Context, token string) *micro.Response {
+	if token == "" {
+		return micro.Unauthorized(MsgErrTokenEmpty, "")
+	}
+
+	decryptToken := m.DecryptToken(ctx, token)
+	if !decryptToken.IsSuccess() {
+		return decryptToken
+	}
+
+	userKey := decryptToken.Get(KeyUserKey)
+	uuid := decryptToken.Get(KeyUuid)
+
+	userCacheResp := m.GetToken(ctx, userKey.String())
+	if !userCacheResp.IsSuccess() {
+		return userCacheResp
+	}
+
+	if uuid.String() != userCacheResp.Get(KeyUuid).String() {
+		g.Log().Debug(ctx, msgLog(MsgErrAuthUuid)+", decryptToken:"+decryptToken.Json()+" cacheValue:"+gconv.String(userCacheResp.Data))
+		return micro.Unauthorized(MsgErrAuthUuid, "")
+	}
+
+	return userCacheResp
+}
+
+// GetToken 通过userKey获取Token
+func (m *RpcxToken) GetToken(ctx context.Context, userKey string) *micro.Response {
+	cacheKey := m.CacheKey + userKey
+
+	userCacheResp := m.getCache(ctx, cacheKey)
+	if !userCacheResp.IsSuccess() {
+		return userCacheResp
+	}
+	userCache := gconv.Map(userCacheResp.Data)
+
+	nowTime := gtime.Now().TimestampMilli()
+	refreshTime := userCache[KeyRefreshTime]
+
+	// 需要进行缓存超时时间刷新
+	if gconv.Int64(refreshTime) == 0 || nowTime > gconv.Int64(refreshTime) {
+		userCache[KeyCreateTime] = gtime.Now().TimestampMilli()
+		userCache[KeyRefreshTime] = gtime.Now().TimestampMilli() + gconv.Int64(m.MaxRefresh)
+		return m.setCache(ctx, cacheKey, userCache)
+	}
+
+	return micro.Success(userCache)
+}
+
+// RemoveToken 删除Token
+func (m *RpcxToken) RemoveToken(ctx context.Context, token string) *micro.Response {
+	decryptToken := m.DecryptToken(ctx, token)
+	if !decryptToken.IsSuccess() {
+		return decryptToken
+	}
+
+	cacheKey := m.CacheKey + decryptToken.Get(KeyUserKey).String()
+	return m.removeCache(ctx, cacheKey)
+}
+
+// EncryptToken token加密方法
+func (m *RpcxToken) EncryptToken(ctx context.Context, userKey string, uuid string) *micro.Response {
+	if userKey == "" {
+		return micro.Fail(MsgErrUserKeyEmpty)
+	}
+
+	if uuid == "" {
+		// 重新生成uuid
+		newUuid, err := gmd5.Encrypt(grand.Letters(10))
+		if err != nil {
+			g.Log().Error(ctx, msgLog(MsgErrAuthUuid), err)
+			return micro.Error(MsgErrAuthUuid)
+		}
+		uuid = newUuid
+	}
+
+	tokenStr := userKey + m.TokenDelimiter + uuid
+
+	token, err := gaes.Encrypt([]byte(tokenStr), m.EncryptKey)
+	if err != nil {
+		g.Log().Error(ctx, msgLog(MsgErrTokenEncrypt), tokenStr, err)
+		return micro.Error(MsgErrTokenEncrypt)
+	}
+
+	return micro.Success(g.Map{
+		//KeyUserKey: userKey,
+		KeyUuid:  uuid,
+		KeyToken: gbase64.EncodeToString(token),
+	})
+}
+
+// DecryptToken token解密方法
+func (m *RpcxToken) DecryptToken(ctx context.Context, token string) *micro.Response {
+	if token == "" {
+		return micro.Fail(MsgErrTokenEmpty)
+	}
+
+	token64, err := gbase64.Decode([]byte(token))
+	if err != nil {
+		g.Log().Error(ctx, msgLog(MsgErrTokenDecode), token, err)
+		return micro.Error(MsgErrTokenDecode)
+	}
+	decryptToken, err2 := gaes.Decrypt(token64, m.EncryptKey)
+	if err2 != nil {
+		g.Log().Error(ctx, msgLog(MsgErrTokenEncrypt), token, err2)
+		return micro.Error(MsgErrTokenEncrypt)
+	}
+	tokenArray := gstr.Split(string(decryptToken), m.TokenDelimiter)
+	if len(tokenArray) < 2 {
+		g.Log().Error(ctx, msgLog(MsgErrTokenLen), token)
+		return micro.Error(MsgErrTokenLen)
+	}
+
+	return micro.Success(g.Map{
+		KeyUserKey: tokenArray[0],
+		KeyUuid:    tokenArray[1],
+	})
+}
+
+// String token解密方法
+func (m *RpcxToken) String() string {
+	return gconv.String(g.Map{
+		// 缓存模式 1 gcache 2 gredis 默认1
+		"CacheMode":        m.CacheMode,
+		"CacheKey":         m.CacheKey,
+		"Timeout":          m.Timeout,
+		"TokenDelimiter":   m.TokenDelimiter,
+		"AuthFailMsg":      m.AuthFailMsg,
+		"MultiLogin":       m.MultiLogin,
+		"MiddlewareType":   m.MiddlewareType,
+		"AuthPaths":        gconv.String(m.AuthPaths),
+		"AuthExcludePaths": gconv.String(m.AuthExcludePaths),
+	})
+}

+ 21 - 20
gtoken/gtoken_cache.go → token/token_cache.go

@@ -1,7 +1,8 @@
-package gtoken
+package token
 
 import (
 	"context"
+	"dashoo.cn/micro_libary/micro"
 	"github.com/gogf/gf/v2/encoding/gjson"
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/os/gcache"
@@ -11,7 +12,7 @@ import (
 )
 
 // setCache 设置缓存
-func (m *GfToken) setCache(ctx context.Context, cacheKey string, userCache g.Map) Resp {
+func (m *RpcxToken) setCache(ctx context.Context, cacheKey string, userCache g.Map) *micro.Response {
 	switch m.CacheMode {
 	case CacheModeCache, CacheModeFile:
 		gcache.Set(ctx, cacheKey, userCache, gconv.Duration(m.Timeout)*time.Millisecond)
@@ -22,58 +23,58 @@ func (m *GfToken) setCache(ctx context.Context, cacheKey string, userCache g.Map
 		cacheValueJson, err1 := gjson.Encode(userCache)
 		if err1 != nil {
 			g.Log().Error(ctx, "[GToken]cache json encode error", err1)
-			return Error("cache json encode error")
+			return micro.Error("cache json encode error")
 		}
 		_, err := g.Redis().Do(ctx, "SETEX", cacheKey, m.Timeout/1000, cacheValueJson)
 		if err != nil {
 			g.Log().Error(ctx, "[GToken]cache set error", err)
-			return Error("cache set error")
+			return micro.Error("cache set error")
 		}
 	default:
-		return Error("cache model error")
+		return micro.Error("cache model error")
 	}
 
-	return Succ(userCache)
+	return micro.Success(userCache)
 }
 
 // getCache 获取缓存
-func (m *GfToken) getCache(ctx context.Context, cacheKey string) Resp {
+func (m *RpcxToken) getCache(ctx context.Context, cacheKey string) *micro.Response {
 	var userCache g.Map
 	switch m.CacheMode {
 	case CacheModeCache, CacheModeFile:
 		userCacheValue, err := gcache.Get(ctx, cacheKey)
 		if err != nil {
 			g.Log().Error(ctx, "[GToken]cache get error", err)
-			return Error("cache get error")
+			return micro.Error("cache get error")
 		}
 		if userCacheValue.IsNil() {
-			return Unauthorized("login timeout or not login", "")
+			return micro.Unauthorized("login timeout or not login", "")
 		}
 		userCache = gconv.Map(userCacheValue)
 	case CacheModeRedis:
 		userCacheJson, err := g.Redis().Do(ctx, "GET", cacheKey)
 		if err != nil {
 			g.Log().Error(ctx, "[GToken]cache get error", err)
-			return Error("cache get error")
+			return micro.Error("cache get error")
 		}
 		if userCacheJson.IsNil() {
-			return Unauthorized("login timeout or not login", "")
+			return micro.Unauthorized("login timeout or not login", "")
 		}
 
 		err = gjson.DecodeTo(userCacheJson, &userCache)
 		if err != nil {
 			g.Log().Error(ctx, "[GToken]cache get json error", err)
-			return Error("cache get json error")
+			return micro.Error("cache get json error")
 		}
 	default:
-		return Error("cache model error")
+		return micro.Error("cache model error")
 	}
 
-	return Succ(userCache)
+	return micro.Success(userCache)
 }
 
 // removeCache 删除缓存
-func (m *GfToken) removeCache(ctx context.Context, cacheKey string) Resp {
+func (m *RpcxToken) removeCache(ctx context.Context, cacheKey string) *micro.Response {
 	switch m.CacheMode {
 	case CacheModeCache, CacheModeFile:
 		_, err := gcache.Remove(ctx, cacheKey)
@@ -88,16 +89,16 @@ func (m *GfToken) removeCache(ctx context.Context, cacheKey string) Resp {
 		_, err = g.Redis().Do(ctx, "DEL", cacheKey)
 		if err != nil {
 			g.Log().Error(ctx, "[GToken]cache remove error", err)
-			return Error("cache remove error")
+			return micro.Error("cache remove error")
 		}
 	default:
-		return Error("cache model error")
+		return micro.Error("cache model error")
 	}
 
-	return Succ("")
+	return micro.Success("")
 }
 
-func (m *GfToken) writeFileCache(ctx context.Context) {
+func (m *RpcxToken) writeFileCache(ctx context.Context) {
 	file := gfile.Temp(CacheModeFileDat)
 	data, e := gcache.Data(ctx)
 	if e != nil {
@@ -106,7 +107,7 @@ func (m *GfToken) writeFileCache(ctx context.Context) {
 	gfile.PutContents(file, gjson.New(data).MustToJsonString())
 }
 
-func (m *GfToken) initFileCache(ctx context.Context) {
+func (m *RpcxToken) initFileCache(ctx context.Context) {
 	file := gfile.Temp(CacheModeFileDat)
 	if !gfile.Exists(file) {
 		return

+ 3 - 5
gtoken/gtoken_conts.go → token/token_conts.go

@@ -1,8 +1,6 @@
-package gtoken
+package token
 
-import (
-	"fmt"
-)
+import "fmt"
 
 const (
 	CacheModeCache   = 1
@@ -17,7 +15,7 @@ const (
 	DefaultTimeout        = 10 * 24 * 60 * 60 * 1000
 	DefaultCacheKey       = "GToken:"
 	DefaultTokenDelimiter = "_"
-	DefaultEncryptKey     = "12345678912345678912345678912345"
+	DefaultEncryptKey     = "dashoo"
 	DefaultAuthFailMsg    = "请求错误或登录超时"
 
 	TraceId = "d5dfce77cdff812161134e55de3c5207"