Logo

Login Guard

Protection contre les tentatives de connexion repetees.

Creer un LoginGuard main.rs
use runique::prelude::*;
use std::sync::Arc;

// Dans main() ou dans le module de routes
let guard = Arc::new(
    LoginGuard::new()
        .max_attempts(5)    // tentatives avant verrouillage
        .lockout_secs(300), // 5 minutes de verrouillage
);

// Nettoyer les entrees expirees regulierement
guard.spawn_cleanup(tokio::time::Duration::from_secs(60));
Creer un LoginGuard main.rs
use runique::prelude::*;
use std::sync::Arc;

// Dans main() ou dans le module de routes
let guard = Arc::new(
    LoginGuard::new()
        .max_attempts(5)    // tentatives avant verrouillage
        .lockout_secs(300), // 5 minutes de verrouillage
);

// Nettoyer les entrees expirees regulierement
guard.spawn_cleanup(tokio::time::Duration::from_secs(60));
Utilisation dans le handler de login handler
pub async fn login(
    mut request: Request,
    Prisme(form): Prisme<LoginForm>,
    State(guard): State<Arc<LoginGuard>>,
) -> AppResult<Response> {
    let username = form.get_string("username");
    let ip       = request.client_ip().unwrap_or_default();

    // Cle par username si rempli, sinon par IP
    if guard.is_locked_for(&username, &ip) {
        let secs = guard.retry_after_secs_for(&username, &ip);
        warning!(request.notices => format!("Compte bloque. Reessayez dans {secs}s."));
        return request.render("auth/login.html");
    }

    if request.is_post() {
        match authenticate(&username, &password, &db).await {
            Some(user) => {
                guard.record_success_for(&username, &ip);
                auth_login(&request.session, user.id, &user.username).await;
                return Ok(Redirect::to("/profil").into_response());
            }
            None => {
                guard.record_failure_for(&username, &ip);
                error!(request.notices => "Identifiants incorrects.");
            }
        }
    }
    request.render("auth/login.html")
}
Utilisation dans le handler de login handler
pub async fn login(
    mut request: Request,
    Prisme(form): Prisme<LoginForm>,
    State(guard): State<Arc<LoginGuard>>,
) -> AppResult<Response> {
    let username = form.get_string("username");
    let ip       = request.client_ip().unwrap_or_default();

    // Cle par username si rempli, sinon par IP
    if guard.is_locked_for(&username, &ip) {
        let secs = guard.retry_after_secs_for(&username, &ip);
        warning!(request.notices => format!("Compte bloque. Reessayez dans {secs}s."));
        return request.render("auth/login.html");
    }

    if request.is_post() {
        match authenticate(&username, &password, &db).await {
            Some(user) => {
                guard.record_success_for(&username, &ip);
                auth_login(&request.session, user.id, &user.username).await;
                return Ok(Redirect::to("/profil").into_response());
            }
            None => {
                guard.record_failure_for(&username, &ip);
                error!(request.notices => "Identifiants incorrects.");
            }
        }
    }
    request.render("auth/login.html")
}