API / Minn\Auth / LoginThrottle

LoginThrottle final readonly class

Minn\Auth\LoginThrottle · public/minn/src/Minn/Auth/LoginThrottle.php · 82 lines

Failed sign-ins per address, so a password guesser meets a wall: twenty failures in fifteen minutes and the address waits out the window. The counters live in the options table (autoload off), one row per address, as "window start:count"; a successful sign-in clears the row. An IPv6 address counts as its /64, the block one subscriber is handed, so stepping through it buys no fresh tries; each failure is counted in one statement, so failures arriving together are all counted.

Constants and properties

constLIMIT = 20
constWINDOW = 900
privatePREFIX = 'minn_login_throttle_'
privatereadonly Minn\Db $db

Promoted from the constructor.

Public

new__construct(Minn\Db $db)#
methodretryAfter(string $address, ?int $now = NULL): ?int#

Seconds the address must wait, or null when it may try.

methodrecordFailure(string $address, ?int $now = NULL): void#

Counts one failed sign-in from an address within the current window.

methodclear(string $address): void#

Forgets an address's failures.

staticsweep(Minn\Db $db, int $now): int#

Drops counters whose window has passed, at most a thousand in one statement, however many addresses have failed; the number dropped.

Internals 2

Private and protected methods: how the class does its work. Not a contract; they change whenever the code is tidied.

privateread(string $address): array#
@return array{0: int, 1: int} window start and failure count
privatekey(string $address): string#

The counter's option: the address's, or an IPv6 address's /64. An address whose first 64 bits are zero (an IPv4 client a dual-stack server shows as ::ffff:a.b.c.d) keeps its whole address, or every IPv4 visitor would share one counter.