tju-yxq opened a new issue, #5357: URL: https://github.com/apache/rocketmq-dashboard/issues/5357
## Problem Login lockouts happen entirely in the dark. The brute-force limiter locks a username for five minutes after five failed attempts, answers further attempts with a 429, and writes a WARN to the application log — and that is the entire footprint of the event. The administrative surface never shows it, so: - An administrator fielding "I can't log in" cannot tell a mistyped password from an active lock without shell access to the server log. - A sustained brute-force attempt against a known username — precisely the signal an operator wants to see — is invisible to the people who could react (watch it, correlate with the audit trail, check whether the account's password is stale). - The lockout feature itself looks like a bug to anyone who does not know it exists: the login page says "try again in N seconds" and nothing anywhere explains that a protection fired. ## Current behavior and reproduction 1. Enter a wrong password five times for any username (existing or not). 2. The sixth attempt answers 429 "Too many failed login attempts; try again in N seconds". 3. Open the console as an administrator: the user management page, session overview, audit feed — nothing mentions the lock. The only trace is a WARN line in the server log. `server/src/main/java/org/apache/rocketmq/studio/auth/LoginRateLimiter.java` holds exactly the needed state (per-username `AttemptState` with `lockedUntilMillis`, around lines 43-50 and 202-208) but exposes only mutation methods (`checkAllowed`, `recordFailure`, `recordSuccess`) plus package-private counters used by tests — there is no read path for the admin surface. ## Proposed behavior - `LoginRateLimiter.activeLockouts()`: a synchronized snapshot of the currently locked usernames with their remaining lock seconds, sorted by soonest unlock. Tracked-but-not-locked usernames (fewer failures than the threshold) stay hidden; expired locks drop out on their own; overflow buckets — shared hash buckets from a saturated tracker — carry no meaningful username and are not listed. - `GET /api/studio-users/login-lockouts` returns the snapshot (admin-gated by the existing interceptor rules for `/api/studio-users/**`). - Read-only by design: locks always lift by themselves after five minutes, so the surface deliberately offers no unlock action — the point is visibility, not intervention. - The session overview card gains a "login lockouts" statistic; when non-zero, each locked username renders as a tag with its remaining lock time (hover: an explanation that the lock lifts automatically). The data refreshes with the page's other overview data. - The state is per-instance, like the limiter and every other login-protection state; a horizontally scaled deployment shows each instance's own view. ## Acceptance criteria - [ ] A locked username appears in the snapshot with the correct remaining seconds; usernames with fewer failures than the threshold do not. - [ ] The snapshot sorts by soonest unlock and drops locks that have expired. - [ ] The endpoint returns the snapshot and is admin-gated by the existing interceptor rules. - [ ] The overview card shows the lockout count, and the per-username tags with remaining time only when the count is non-zero. - [ ] No unlock action exists anywhere; the hover help states the lock lifts by itself. - [ ] Locking behavior (`checkAllowed`/`recordFailure`/`recordSuccess`) is unchanged. ## Importance Must-have. Brute-force visibility is the reason the lockout feature exists at all; today the protection fires blind. Workaround: read the server log on the host — unavailable to console-only operators, rotated away quickly, and shows no live remaining time. ## Duplicate check Searched open and closed issues and PRs for `lockout`, `brute force`, and `locked account`. The existing items harden the limiter's mechanics (#2378 bounded state, #3045 lock preservation, #4159 open — ordering bug) or mention lockouts in passing; none proposes an administrative visibility surface. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
