fix: 登录频率限制 bug — lock_until=0 导致计数被清零

根因: 初始 lock_until=0 时 now >= 0 + 60 恒为真, 每次请求都清除计数
修复: lock_until 改用 None 表示未锁定, 仅非 None 时做过期判断

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
qinglong
2026-06-13 13:46:29 +08:00
parent a75b9d0975
commit 2f9063d6d4
3 changed files with 36 additions and 8 deletions
+19 -3
View File
@@ -9,6 +9,10 @@ commands:
permissions: permissions:
- framework.scaffold.plugin - framework.scaffold.plugin
source: internal source: internal
echo: &id001
description: echo input
permissions: []
source: plugin.example_plugin
help: help:
description: 显示帮助信息 description: 显示帮助信息
permissions: permissions:
@@ -19,6 +23,11 @@ commands:
permissions: permissions:
- framework.command.history.read - framework.command.history.read
source: internal source: internal
install:
description: '从在线索引安装插件: install <name> 或 install --list'
permissions:
- framework.plugin.install
source: internal
netdiag: netdiag:
description: 网络服务诊断 description: 网络服务诊断
permissions: permissions:
@@ -29,6 +38,10 @@ commands:
permissions: permissions:
- framework.permission.read - framework.permission.read
source: internal source: internal
plugin_status: &id002
description: show status
permissions: []
source: plugin.example_plugin
pm_plugin_status: pm_plugin_status:
description: '权限管理: 查看插件权限状态' description: '权限管理: 查看插件权限状态'
permissions: permissions:
@@ -84,6 +97,9 @@ commands:
permissions: permissions:
- framework.command.test - framework.command.test
source: internal source: internal
last_updated: 1742.472300949 last_updated: 11552.003166269
plugin_commands: {} plugin_commands:
total_commands: 17 example_plugin:
echo: *id001
plugin_status: *id002
total_commands: 20
+9 -1
View File
@@ -1,9 +1,17 @@
http_port: 4200 http_port: 4200
last_updated: 316707.287225746 last_updated: 11552.015952154
plugin_routes: plugin_routes:
example_plugin: example_plugin:
- methods: - methods:
- GET - GET
path: /example_plugin/api/example/info path: /example_plugin/api/example/info
require_auth: false require_auth: false
- methods:
- POST
path: /example_plugin/api/plugin/echo
require_auth: true
- methods:
- POST
path: /example_plugin/api/plugin/plugin_status
require_auth: true
websocket_port: 4240 websocket_port: 4240
+8 -4
View File
@@ -24,20 +24,24 @@ def _check_rate_limit(ip: str) -> bool:
entry = _LOGIN_FAILS.get(ip) entry = _LOGIN_FAILS.get(ip)
if entry: if entry:
fail_count, lock_until = entry fail_count, lock_until = entry
if now < lock_until: if lock_until and now < lock_until:
return False # still locked return False # still locked
if now >= lock_until + _LOCK_SECONDS: if lock_until and now >= lock_until:
_LOGIN_FAILS.pop(ip, None) # expired, reset _LOGIN_FAILS.pop(ip, None) # lock expired, reset
return True return True
def _record_fail(ip: str): def _record_fail(ip: str):
now = time.time() now = time.time()
entry = _LOGIN_FAILS.get(ip, [0, 0]) entry = _LOGIN_FAILS.get(ip)
if entry is None:
entry = [0, None]
entry[0] += 1 entry[0] += 1
if entry[0] >= _MAX_FAILS: if entry[0] >= _MAX_FAILS:
entry[1] = now + _LOCK_SECONDS entry[1] = now + _LOCK_SECONDS
logger.warning(f"🔒 IP {ip} 登录锁定 {_LOCK_SECONDS}s ({_MAX_FAILS} 次失败)") logger.warning(f"🔒 IP {ip} 登录锁定 {_LOCK_SECONDS}s ({_MAX_FAILS} 次失败)")
else:
logger.debug(f"IP {ip} 登录失败计数: {entry[0]}/{_MAX_FAILS}")
_LOGIN_FAILS[ip] = entry _LOGIN_FAILS[ip] = entry