1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 15:51:06 +01:00
actix-extras/actix-session
John Vandenberg 48646d1bd3
build(deps): update derive_more to v1.0 (#458)
* build(deps): update derive_more to v1.0

* chore: remove overspecified deps

* chore: use from the derive module

* chore: restore unrelated version reqs

---------

Co-authored-by: Rob Ede <robjtede@icloud.com>
2024-08-18 14:21:56 +00:00
..
examples refactor: use tracing in session examples 2024-06-09 20:34:09 +01:00
src build(deps): update derive_more to v1.0 (#458) 2024-08-18 14:21:56 +00:00
tests feat(session): use real async traits (#365) 2024-01-04 04:10:46 +00:00
Cargo.toml build(deps): update derive_more to v1.0 (#458) 2024-08-18 14:21:56 +00:00
CHANGES.md chore(actix-session): prepare release 0.10.0 2024-08-07 00:57:54 +01:00
LICENSE-APACHE add license files 2019-06-01 17:25:29 +06:00
LICENSE-MIT add license files 2019-06-01 17:25:29 +06:00
README.md docs(session): doc adding features using cargo add 2024-08-07 01:03:40 +01:00

actix-session

Session management for Actix Web.

crates.io Documentation Apache 2.0 or MIT licensed Dependency Status

Session management for Actix Web.

The HTTP protocol, at a first glance, is stateless: the client sends a request, the server parses its content, performs some processing and returns a response. The outcome is only influenced by the provided inputs (i.e. the request content) and whatever state the server queries while performing its processing.

Stateless systems are easier to reason about, but they are not quite as powerful as we need them to be - e.g. how do you authenticate a user? The user would be forced to authenticate for every single request. That is, for example, how 'Basic' Authentication works. While it may work for a machine user (i.e. an API client), it is impractical for a person—you do not want a login prompt on every single page you navigate to!

There is a solution - sessions. Using sessions the server can attach state to a set of requests coming from the same client. They are built on top of cookies - the server sets a cookie in the HTTP response (Set-Cookie header), the client (e.g. the browser) will store the cookie and play it back to the server when sending new requests (using the Cookie header).

We refer to the cookie used for sessions as a session cookie. Its content is called session key (or session ID), while the state attached to the session is referred to as session state.

actix-session provides an easy-to-use framework to manage sessions in applications built on top of Actix Web. [SessionMiddleware] is the middleware underpinning the functionality provided by actix-session; it takes care of all the session cookie handling and instructs the storage backend to create/delete/update the session state based on the operations performed against the active [Session].

actix-session provides some built-in storage backends: (CookieSessionStore, RedisSessionStore) - you can create a custom storage backend by implementing the SessionStore trait.

Further reading on sessions:

Getting started

To start using sessions in your Actix Web application you must register [SessionMiddleware] as a middleware on your App:

use actix_web::{web, App, HttpServer, HttpResponse, Error};
use actix_session::{Session, SessionMiddleware, storage::RedisSessionStore};
use actix_web::cookie::Key;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    // When using `Key::generate()` it is important to initialize outside of the
    // `HttpServer::new` closure. When deployed the secret key should be read from a
    // configuration file or environment variables.
    let secret_key = Key::generate();

    let redis_store = RedisSessionStore::new("redis://127.0.0.1:6379")
        .await
        .unwrap();

    HttpServer::new(move ||
            App::new()
            // Add session management to your application using Redis for session state storage
            .wrap(
                SessionMiddleware::new(
                    redis_store.clone(),
                    secret_key.clone(),
                )
            )
            .default_service(web::to(|| HttpResponse::Ok())))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

The session state can be accessed and modified by your request handlers using the [Session] extractor. Note that this doesn't work in the stream of a streaming response.

use actix_web::Error;
use actix_session::Session;

fn index(session: Session) -> Result<&'static str, Error> {
    // access the session state
    if let Some(count) = session.get::<i32>("counter")? {
        println!("SESSION value: {}", count);
        // modify the session state
        session.insert("counter", count + 1)?;
    } else {
        session.insert("counter", 1)?;
    }

    Ok("Welcome!")
}

Choosing A Backend

By default, actix-session does not provide any storage backend to retrieve and save the state attached to your sessions. You can enable:

  • a purely cookie-based "backend", CookieSessionStore, using the cookie-session feature flag.

    cargo add actix-session --features=cookie-session
    
  • a Redis-based backend via the [redis] crate, RedisSessionStore, using the redis-session feature flag.

    cargo add actix-session --features=redis-session
    

    Add the redis-session-native-tls feature flag if you want to connect to Redis using a secure connection (via the native-tls crate):

    cargo add actix-session --features=redis-session-native-tls
    

    If you, instead, prefer depending on rustls, use the redis-session-rustls feature flag:

    cargo add actix-session --features=redis-session-rustls
    

You can implement your own session storage backend using the SessionStore trait.