package utils import ( "errors" "strings" "sync" "time" "git.qianqiusoft.com/qianqiusoft/light-apiengine/config" "git.qianqiusoft.com/qianqiusoft/light-apiengine/entitys" "git.qianqiusoft.com/qianqiusoft/light-apiengine/logs" ) type TokenStore interface { Get(string) *entitys.Token Set(string, *entitys.Token) Remove(key string) Refresh(key string) *entitys.Token } type MemoryStore struct { name string lock *sync.RWMutex tokens map[string]*entitys.Token } var globalTokenStore TokenStore func init() { memoryStore := &MemoryStore{name: "sso", lock: new(sync.RWMutex), tokens: make(map[string]*entitys.Token)} globalTokenStore = memoryStore go memoryStore.startTokenCheckProcess() } func GetGlobalTokenStore() TokenStore { return globalTokenStore } func SetGlobalTokenStore(store TokenStore) { globalTokenStore = store } func (t *MemoryStore) Get(key string) *entitys.Token { t.lock.RLock() defer t.lock.RUnlock() if val, ok := t.tokens[key]; ok { return val } return nil } func (t *MemoryStore) Set(key string, v *entitys.Token) { t.lock.Lock() defer t.lock.Unlock() if val, ok := t.tokens[key]; !ok { t.tokens[key] = v } else if val != v { t.tokens[key] = v } } func (t *MemoryStore) Remove(key string) { t.lock.Lock() defer t.lock.Unlock() delete(t.tokens, key) } func (t *MemoryStore) Refresh(key string) *entitys.Token { t.lock.Lock() defer t.lock.Unlock() val, ok := t.tokens[key] if ok { val.TimeStamp = uint64(time.Now().UnixNano()) } return val } func (t *MemoryStore) startTokenCheckProcess() { autoRefresh := config.AppConfig.AutoRefresh if !autoRefresh { return } var duration time.Duration = time.Second * 3600 t1 := time.NewTicker(duration) for { select { case <-t1.C: t.lock.Lock() keys := []string{} for k, v := range t.tokens { timestampt := time.Unix(int64(v.TimeStamp), 0) subval := time.Now().Sub(timestampt) if subval.Seconds() < 0 || subval.Seconds() > 3600 { keys = append(keys, k) } } for _, k := range keys { delete(t.tokens, k) } t.lock.Unlock() } } } func Validate(accessToken, loginId string, domain string) (*entitys.Token, error) { token := globalTokenStore.Get(loginId + domain) if token != nil { if strings.EqualFold(token.AccessToken, accessToken) { globalTokenStore.Refresh(loginId + domain) return token, nil } else { logs.Error(token.AccessToken, "is not equal to", accessToken) return token, errors.New(token.AccessToken + " is not equal to " + accessToken) } } else { logs.Error("can not get the token of", loginId+domain) return token, errors.New("can not get the token of " + loginId + domain) } } func TokenValidate(token string) (*entitys.Token, error) { tokenRaw := globalTokenStore.Get(token) if strings.EqualFold(tokenRaw.AccessToken, token) { globalTokenStore.Refresh(token) return tokenRaw, nil } else { logs.Error(tokenRaw.AccessToken, "is not equal to", token) return tokenRaw, errors.New(tokenRaw.AccessToken + " is not equal to " + token) } }