Skip to main content

LoginRateLimiter

Struct LoginRateLimiter 

Source
pub struct LoginRateLimiter { /* private fields */ }
Expand description

In-memory counter of recent failed login attempts, keyed by email.

After LoginRateLimiter::MAX_FAILURES failures, further attempts for the same key are rejected for LoginRateLimiter::LOCKOUT. A single successful login clears the counter.

Scope: per-email, not per-IP. Stops targeted brute force against a single account. A distributed attack (many emails, many sources) is not defended; per-IP rate limiting requires the server pipeline to propagate the client address into the request context, which is deferred to a later pass.

Implementations§

Source§

impl LoginRateLimiter

Source

pub const MAX_FAILURES: u32 = 5

Lock an account’s login attempts for 60s after 5 failures in the current lockout window. Conservative defaults; tune via LoginRateLimiter::with_params in tests or forks.

Source

pub const LOCKOUT: StdDuration

Source

pub fn new() -> Self

Source

pub fn with_params(max_failures: u32, lockout: StdDuration) -> Self

Construct with custom thresholds. Used by tests to exercise lockout behaviour on a shorter clock.

Source

pub fn global() -> &'static Self

Process-wide shared limiter used by the login handler. Lazily created on first access. In-process only — resets on restart, which is a deliberate trade-off for simplicity in 0.4.0.

Source

pub fn check(&self, key: &str) -> Result<(), StdDuration>

Return Ok(()) if a login attempt is permitted for this key. If the key is currently locked out, return the time remaining until the lockout expires.

Source

pub fn record_failure(&self, key: &str)

Record a failed login for key. On the transition to the threshold, stamps locked_until to “now + LOCKOUT” so check will reject further attempts until the clock advances.

Source

pub fn record_success(&self, key: &str)

Clear the counter for key. Called on every successful login so a user who mistypes once then logs in isn’t held to the strike count.

Source

pub fn compose_key(email: &str, ip: Option<&str>) -> String

Compose a multi-axis rate-limit key from an email (required) and an optional IP.

The login handler calls this with whatever it has in hand — peer_addr() is available when the server provided it, otherwise we fall back to email-only. Including the IP means one attacker hammering many emails is throttled by IP too, and one email being hit from many IPs is still throttled by email.

This is the documented extension point for future per-IP limiting beyond the login path. Wrap the key any way a caller sees fit (e.g. format!("api:{user_id}")); the limiter itself only compares strings.

Trait Implementations§

Source§

impl Default for LoginRateLimiter

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more