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]

Reply via email to