|
| 1 | +package server |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/base64" |
| 5 | + "encoding/binary" |
| 6 | + "time" |
| 7 | + |
| 8 | + "github.com/emmansun/gmsm/sm3" |
| 9 | + |
| 10 | + "github.com/OpenNHP/opennhp/common" |
| 11 | + "github.com/OpenNHP/opennhp/log" |
| 12 | +) |
| 13 | + |
| 14 | +type ACTokenEntry struct { |
| 15 | + User *common.AgentUser |
| 16 | + ResourceId string |
| 17 | + ACTokens map[string]string |
| 18 | + OpenTime int |
| 19 | + ExpireTime time.Time |
| 20 | +} |
| 21 | + |
| 22 | +type TokenToACMap = map[string]*ACTokenEntry // server access token mapped into mutiple AC tokens |
| 23 | +type TokenStore = map[string]TokenToACMap // upper layer of tokens, indexed by first two characters |
| 24 | + |
| 25 | +func (s *UdpServer) GenerateAccessToken(entry *ACTokenEntry) string { |
| 26 | + var tsBytes [8]byte |
| 27 | + currTime := time.Now().UnixNano() |
| 28 | + |
| 29 | + hash := sm3.New() |
| 30 | + binary.BigEndian.PutUint64(tsBytes[:], uint64(currTime)) |
| 31 | + au := entry.User |
| 32 | + hash.Write([]byte(s.config.Hostname + au.UserId + au.DeviceId + au.OrganizationId + au.AuthServiceId)) |
| 33 | + hash.Write(tsBytes[:]) |
| 34 | + token := base64.StdEncoding.EncodeToString(hash.Sum(nil)) |
| 35 | + hash.Reset() |
| 36 | + |
| 37 | + s.tokenStoreMutex.Lock() |
| 38 | + defer s.tokenStoreMutex.Unlock() |
| 39 | + |
| 40 | + entry.ExpireTime = time.Now().Add(time.Duration(entry.OpenTime) * time.Second) |
| 41 | + tokenMap, found := s.tokenStore[token[0:1]] |
| 42 | + if found { |
| 43 | + tokenMap[token] = entry |
| 44 | + } else { |
| 45 | + tokenMap := make(TokenToACMap) |
| 46 | + tokenMap[token] = entry |
| 47 | + s.tokenStore[token[0:1]] = tokenMap |
| 48 | + } |
| 49 | + |
| 50 | + return token |
| 51 | +} |
| 52 | + |
| 53 | +func (s *UdpServer) VerifyAccessToken(token string) *ACTokenEntry { |
| 54 | + s.tokenStoreMutex.Lock() |
| 55 | + defer s.tokenStoreMutex.Unlock() |
| 56 | + |
| 57 | + tokenMap, found := s.tokenStore[token[0:1]] |
| 58 | + if found { |
| 59 | + entry, found := tokenMap[token] |
| 60 | + if found { |
| 61 | + return entry |
| 62 | + } |
| 63 | + } |
| 64 | + |
| 65 | + return nil |
| 66 | +} |
| 67 | + |
| 68 | +func (s *UdpServer) tokenStoreRefreshRoutine() { |
| 69 | + defer s.wg.Done() |
| 70 | + defer log.Info("tokenStoreRefreshRoutine stopped") |
| 71 | + |
| 72 | + log.Info("tokenStoreRefreshRoutine started") |
| 73 | + |
| 74 | + for { |
| 75 | + select { |
| 76 | + case <-s.signals.stop: |
| 77 | + return |
| 78 | + |
| 79 | + case <-time.After(TokenStoreRefreshInterval * time.Second): |
| 80 | + s.tokenStoreMutex.Lock() |
| 81 | + defer s.tokenStoreMutex.Unlock() |
| 82 | + |
| 83 | + now := time.Now() |
| 84 | + for head, tokenMap := range s.tokenStore { |
| 85 | + for token, entry := range tokenMap { |
| 86 | + if now.After(entry.ExpireTime) { |
| 87 | + log.Info("[TokenStore] token %s expired, remove", token) |
| 88 | + delete(tokenMap, token) |
| 89 | + } |
| 90 | + } |
| 91 | + if len(tokenMap) == 0 { |
| 92 | + delete(s.tokenStore, head) |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + } |
| 97 | +} |
0 commit comments