InMemoryLoginFailureTracker.kt

package io.github.lishangbu.avalon.oauth2.authorizationserver.login

import io.github.lishangbu.avalon.oauth2.common.properties.Oauth2Properties
import java.time.Clock
import java.time.Duration
import java.util.concurrent.ConcurrentHashMap

/** 基于内存的登录失败跟踪器实现 */
class InMemoryLoginFailureTracker(
    properties: Oauth2Properties?,
    clock: Clock = Clock.systemUTC(),
) : AbstractLoginFailureTracker(properties, clock) {
    /** 尝试次数 */
    private val attempts = ConcurrentHashMap<String, LoginFailureState>()

    /** 获取剩余锁定时长 */
    override fun getRemainingLock(username: String?): Duration? {
        if (!isEnabled()) {
            return null
        }
        val key = normalize(username) ?: return null
        val state = attempts[key] ?: return null
        val currentTime = now()
        val remainingLock = getRemainingLock(state, currentTime)
        if (remainingLock == null && state.lockUntil != null) {
            attempts.remove(key, state)
        }
        return remainingLock
    }

    /** 处理失败 */
    override fun onFailure(username: String?) {
        if (!isEnabled()) {
            return
        }
        val key = normalize(username) ?: return
        val currentTime = now()
        attempts.compute(key) { _, current ->
            nextState(current, currentTime)
        }
    }

    /** 处理成功 */
    override fun onSuccess(username: String?) {
        val key = normalize(username) ?: return
        attempts.remove(key)
    }
}