Session

Middleware zur Unterstützung von Session.

Was ist eine Session

Eine Session ist eine serverseitig gespeicherte Benutzerdatenmenge, die typischerweise zur Verfolgung des Benutzerstatus und zur Speicherung temporärer Daten verwendet wird. In Webanwendungen ermöglicht die Session die Lösung des zustandslosen Problems des HTTP-Protokolls, sodass der Server mehrere Anfragen desselben Benutzers erkennen kann.

Verwendung von Session in Salvo

In Salvo bietet die Session-Middleware eine einfache API zum Lesen und Schreiben von Sitzungsdaten. Über SessionDepot kann die Sitzungsinstanz abgerufen werden, und mit Methoden wie get, set und remove können Sitzungsdaten verwaltet werden.

Häufige Anwendungsfälle

  • Benutzerauthentifizierung und Login-Statusverwaltung
  • Temporäre Speicherung von Formulardaten
  • Speicherung von Benutzereinstellungen

Beispielcode

main.rs
Cargo.toml
session-login/src/main.rs
use salvo::prelude::*;
use salvo::session::{CookieStore, Session, SessionDepotExt, SessionHandler};

#[tokio::main]
async fn main() {
    tracing_subscriber::fmt().init();
    let session_handler = SessionHandler::builder(
        CookieStore::new(),
        b"secretabsecretabsecretabsecretabsecretabsecretabsecretabsecretab",
    )
    .build()
    .unwrap();
    let router = Router::new()
        .hoop(session_handler)
        .get(home)
        .push(Router::with_path("login").get(login).post(login))
        .push(Router::with_path("logout").get(logout));

    let acceptor = TcpListener::new("0.0.0.0:5800").bind().await;
    Server::new(acceptor).serve(router).await;
}

#[handler]
pub async fn login(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    if req.method() == salvo::http::Method::POST {
        let mut session = Session::new();
        session
            .insert("username", req.form::<String>("username").await.unwrap())
            .unwrap();
        depot.set_session(session);
        res.render(Redirect::other("/"));
    } else {
        res.render(Text::Html(LOGIN_HTML));
    }
}

#[handler]
pub async fn logout(depot: &mut Depot, res: &mut Response) {
    if let Some(session) = depot.session_mut() {
        session.remove("username");
    }
    res.render(Redirect::other("/"));
}

#[handler]
pub async fn home(depot: &mut Depot, res: &mut Response) {
    let mut content = r#"<a href="login">Login</h1>"#.into();
    if let Some(session) = depot.session_mut() {
        if let Some(username) = session.get::<String>("username") {
            content = format!(r#"Hello, {username}. <br><a href="logout">Logout</h1>"#);
        }
    }
    res.render(Text::Html(content));
}

static LOGIN_HTML: &str = r#"<!DOCTYPE html>
<html>
    <head>
        <title>Login</title>
    </head>
    <body>
        <form action="/login" method="post">
            <h1>Login</h1>
            <input type="text" name="username" />
            <button type="submit" id="submit">Submit</button>
        </form>
    </body>
</html>
"#;