fix: P0-02 prevent login attempt counter race condition
Add atomic Increment method to cache layers: - L2Cache interface: add Increment method signature - RedisCache: implement using Redis INCRBY - L1Cache: implement with mutex-protected counter - CacheManager: add Increment that updates both L1 and L2 Update incrementFailAttempts to use atomic Increment instead of Get-Increment-Set pattern, preventing TOCTOU race.
This commit is contained in:
41
internal/cache/l1.go
vendored
41
internal/cache/l1.go
vendored
@@ -169,3 +169,44 @@ func (c *L1Cache) Cleanup() {
|
||||
c.removeFromAccessOrder(key)
|
||||
}
|
||||
}
|
||||
|
||||
// Increment 原子递增(用于登录失败计数器等原子操作场景)
|
||||
func (c *L1Cache) Increment(key string, delta int64, ttl time.Duration) int64 {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
var expiration int64
|
||||
if ttl > 0 {
|
||||
expiration = time.Now().Add(ttl).UnixNano()
|
||||
}
|
||||
|
||||
current := int64(0)
|
||||
if item, ok := c.items[key]; ok {
|
||||
if item.Expired() {
|
||||
delete(c.items, key)
|
||||
c.removeFromAccessOrder(key)
|
||||
} else {
|
||||
if v, ok := item.Value.(int64); ok {
|
||||
current = v
|
||||
} else if v, ok := item.Value.(int); ok {
|
||||
current = int64(v)
|
||||
} else if v, ok := item.Value.(float64); ok {
|
||||
current = int64(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newVal := current + delta
|
||||
c.items[key] = &CacheItem{
|
||||
Value: newVal,
|
||||
Expiration: expiration,
|
||||
}
|
||||
|
||||
if _, exists := c.items[key]; !exists {
|
||||
c.accessOrder = append(c.accessOrder, key)
|
||||
} else {
|
||||
c.updateAccessOrder(key)
|
||||
}
|
||||
|
||||
return newVal
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user