diff --git a/api/waf_login.go b/api/waf_login.go index b859edf..dd3c3d0 100644 --- a/api/waf_login.go +++ b/api/waf_login.go @@ -89,15 +89,26 @@ func (w *WafLoginApi) LoginApi(c *gin.Context) { } // 密码正确,清除错误计数 global.GCACHE_WAFCACHE.Remove(cacheKey) - //如果存在旧的状态删除 - oldTokenInfo := wafTokenInfoService.GetInfoByLoginAccount(req.LoginAccount) - if oldTokenInfo.Id != "" { - wafTokenInfoService.DelApiByAccount(oldTokenInfo.LoginAccount) + + //如果存在旧的状态删除 相同帐号 只允许一个 + allTokenInfo := wafTokenInfoService.GetAllTokenInfoByLoginAccount(req.LoginAccount) + if allTokenInfo != nil { + for i := 0; i < len(allTokenInfo); i++ { + oldTokenInfo := allTokenInfo[i] + if oldTokenInfo.Id != "" { + wafTokenInfoService.DelApiByAccount(oldTokenInfo.LoginAccount) + global.GCACHE_WAFCACHE.Remove(enums.CACHE_TOKEN + oldTokenInfo.AccessToken) + } + } } + //记录状态 accessToken := utils.Md5String(uuid.NewV4().String()) tokenInfo := wafTokenInfoService.AddApi(bean.LoginAccount, accessToken, c.ClientIP()) + //令牌记录到cache里 + global.GCACHE_WAFCACHE.SetWithTTl(enums.CACHE_TOKEN+accessToken, *tokenInfo, time.Duration(global.GCONFIG_RECORD_TOKEN_EXPIRE_MINTUTES)*time.Minute) + //通知信息 noticeStr := fmt.Sprintf("登录IP:%s 归属地区:%s", clientIP, clientCountry) global.GQEQUE_MESSAGE_DB.Enqueue(innerbean.OperatorMessageInfo{ diff --git a/cache/waf_cache.go b/cache/waf_cache.go index 43bace7..3009e6b 100644 --- a/cache/waf_cache.go +++ b/cache/waf_cache.go @@ -1,6 +1,7 @@ package cache import ( + "SamWaf/common/zlog" "errors" "strings" "sync" @@ -107,6 +108,7 @@ func (wafCache *WafCache) GetLastTime(key string) (time.Time, error) { if time.Since(item.createTime) <= item.ttl { return item.lastTime, nil } + zlog.Debug("GetLastTime CLEAR CACHE EXPIRE :" + key) delete(wafCache.cache, key) return time.Time{}, errors.New("数据已过期") } @@ -114,6 +116,7 @@ func (wafCache *WafCache) ClearExpirationCache() { now := time.Now() for key, item := range wafCache.cache { if now.Sub(item.createTime) > item.ttl { + zlog.Debug("ClearExpirationCache CLEAR CACHE EXPIRE :" + key) delete(wafCache.cache, key) } } diff --git a/enums/cache_enum.go b/enums/cache_enum.go index 8780b32..4bd049c 100644 --- a/enums/cache_enum.go +++ b/enums/cache_enum.go @@ -4,4 +4,5 @@ const ( CACHE_LOGIN_ERROR = "CACHE_LOGIN_ERROR" //登录密码错误 CACHE_NOTICE_PRE = "CACHE_NOTICE_PRE" //通知前缀 CACHE_CCVISITBAN_PRE = "CACHE_CCVISITBAN_PRE_" //CC封禁前缀 + CACHE_TOKEN = "CACHE_TOKEN" //鉴权信息 ) diff --git a/global/config.go b/global/config.go index f5eb33f..9dcda62 100644 --- a/global/config.go +++ b/global/config.go @@ -23,4 +23,6 @@ var ( //GCONFIG_RECORD_PATCH_VERSION_CORE int64 = 20250106 // 核心数据库补丁日期 //GCONFIG_RECORD_PATCH_VERSION_LOG int64 = 20250106 // 日志数据库补丁日期 GCONFIG_RECORD_ALL_SRC_BYTE_INFO int64 = 0 //记录原始信息(默认不开启) + + GCONFIG_RECORD_TOKEN_EXPIRE_MINTUTES int64 = 5 //令牌有效期 单位分钟 ) diff --git a/middleware/auth_api_check.go b/middleware/auth_api_check.go index a98ca02..b9c77a2 100644 --- a/middleware/auth_api_check.go +++ b/middleware/auth_api_check.go @@ -2,10 +2,15 @@ package middleware import ( "SamWaf/common/zlog" + "SamWaf/enums" + "SamWaf/global" + "SamWaf/model" "SamWaf/model/common/response" "SamWaf/service/waf_service" + "fmt" "github.com/gin-gonic/gin" "strings" + "time" ) var ( @@ -31,16 +36,26 @@ func Auth() gin.HandlerFunc { c.Abort() return } else { - bean := wafTokenInfoService.GetInfoByAccessToken(tokenStr) - if bean.Id == "" { + //检查是否存在 + isTokenExist := global.GCACHE_WAFCACHE.IsKeyExist(enums.CACHE_TOKEN + tokenStr) + if !isTokenExist { response.AuthFailWithMessage("非法口令", c) c.Abort() return + } else { + tokenInfo := global.GCACHE_WAFCACHE.Get(enums.CACHE_TOKEN + tokenStr).(model.TokenInfo) + if tokenInfo.LoginIp != c.ClientIP() { + zlog.Error(fmt.Sprintf("登录IP不一致,请求拒绝,原IP:%v 当前IP:%v", tokenInfo.LoginIp, c.ClientIP())) + global.GCACHE_WAFCACHE.Remove(enums.CACHE_TOKEN + tokenStr) + response.AuthFailWithMessage("本次登录IP和上次登录IP不一致需要重新登录", c) + c.Abort() + return + } else { + //刷新token时间 + global.GCACHE_WAFCACHE.SetWithTTl(enums.CACHE_TOKEN+tokenStr, tokenInfo, time.Duration(global.GCONFIG_RECORD_TOKEN_EXPIRE_MINTUTES)*time.Minute) + } } } - //zlog.Debug("有token:" + tokenStr) - // 将 claims 中的用户信息存储在 context 中 - //c.Set("userId", claims.UserId) // 这里执行路由 HandlerFunc c.Next() diff --git a/service/waf_service/waf_token_info.go b/service/waf_service/waf_token_info.go index 4d24e5d..4e884aa 100644 --- a/service/waf_service/waf_token_info.go +++ b/service/waf_service/waf_token_info.go @@ -61,6 +61,13 @@ func (receiver *WafTokenInfoService) GetInfoByLoginAccount(loginAccount string) return bean } +// GetAllTokenInfoByLoginAccount 通过登录account获取账号信息 +func (receiver *WafTokenInfoService) GetAllTokenInfoByLoginAccount(loginAccount string) []model.TokenInfo { + var bean []model.TokenInfo + global.GWAF_LOCAL_DB.Where("login_account=? ", loginAccount).Find(&bean) + return bean +} + /* * 获取一个可用的token TODO 将来应该是一个 diff --git a/waftask/task_config.go b/waftask/task_config.go index 93f22b1..3e79b6b 100644 --- a/waftask/task_config.go +++ b/waftask/task_config.go @@ -54,6 +54,9 @@ func setConfigIntValue(name string, value int64, change int) { case "record_all_src_byte_info": global.GCONFIG_RECORD_ALL_SRC_BYTE_INFO = value break + case "token_expire_time": + global.GCONFIG_RECORD_TOKEN_EXPIRE_MINTUTES = value + break default: zlog.Warn("Unknown config item:", name) } @@ -162,5 +165,6 @@ func TaskLoadSetting(initLoad bool) { updateConfigIntItem(initLoad, "network", "keepalive_time_out", global.GCONFIG_RECORD_KEEPALIVE_TIME_OUT, "保持活动超时(默认30s)", "int", "") updateConfigIntItem(initLoad, "system", "record_all_src_byte_info", global.GCONFIG_RECORD_ALL_SRC_BYTE_INFO, "启动记录原始请求BODY报文(1启动 0关闭)", "int", "") + updateConfigIntItem(initLoad, "system", "token_expire_time", global.GCONFIG_RECORD_TOKEN_EXPIRE_MINTUTES, "管理平台令牌有效期,单位分钟(默认5分钟)", "int", "") }