1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +01:00

add some doc examples to -session

This commit is contained in:
Rob Ede 2022-08-09 01:03:28 +01:00
parent bad6159516
commit a325f5dd02
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
2 changed files with 67 additions and 40 deletions

View File

@ -1,13 +1,14 @@
//! Configuration options to tune the behaviour of [`SessionMiddleware`]. //! Configuration options to tune the behaviour of [`SessionMiddleware`].
use actix_web::cookie::{time::Duration, Key, SameSite}; use actix_web::cookie::{time::Duration, Key, SameSite};
use derive_more::From;
use crate::{storage::SessionStore, SessionMiddleware}; use crate::{storage::SessionStore, SessionMiddleware};
/// Determines what type of session cookie should be used and how its lifecycle should be managed. /// Determines what type of session cookie should be used and how its lifecycle should be managed.
/// ///
/// Used by [`SessionMiddlewareBuilder::session_lifecycle`]. /// Used by [`SessionMiddlewareBuilder::session_lifecycle`].
#[derive(Debug, Clone)] #[derive(Debug, Clone, From)]
#[non_exhaustive] #[non_exhaustive]
pub enum SessionLifecycle { pub enum SessionLifecycle {
/// The session cookie will expire when the current browser session ends. /// The session cookie will expire when the current browser session ends.
@ -27,18 +28,6 @@ pub enum SessionLifecycle {
PersistentSession(PersistentSession), PersistentSession(PersistentSession),
} }
impl From<BrowserSession> for SessionLifecycle {
fn from(session: BrowserSession) -> Self {
Self::BrowserSession(session)
}
}
impl From<PersistentSession> for SessionLifecycle {
fn from(session: PersistentSession) -> Self {
Self::PersistentSession(session)
}
}
/// A [session lifecycle](SessionLifecycle) strategy where the session cookie expires when the /// A [session lifecycle](SessionLifecycle) strategy where the session cookie expires when the
/// browser's current session ends. /// browser's current session ends.
/// ///
@ -46,6 +35,9 @@ impl From<PersistentSession> for SessionLifecycle {
/// continue running in the background when the browser is closed—session cookies are not deleted /// continue running in the background when the browser is closed—session cookies are not deleted
/// and they will still be available when the browser is opened again. Check the documentation of /// and they will still be available when the browser is opened again. Check the documentation of
/// the browsers you are targeting for up-to-date information. /// the browsers you are targeting for up-to-date information.
///
/// Due to its `Into<SessionLifecycle>` implementation, a `BrowserSession` can be passed directly
/// to [`SessionMiddlewareBuilder::session_lifecycle()`].
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BrowserSession { pub struct BrowserSession {
state_ttl: Duration, state_ttl: Duration,
@ -103,6 +95,26 @@ impl Default for BrowserSession {
/// Persistent cookies have a pre-determined expiration, specified via the `Max-Age` or `Expires` /// Persistent cookies have a pre-determined expiration, specified via the `Max-Age` or `Expires`
/// attribute. They do not disappear when the current browser session ends. /// attribute. They do not disappear when the current browser session ends.
/// ///
/// Due to its `Into<SessionLifecycle>` implementation, a `PersistentSession` can be passed directly
/// to [`SessionMiddlewareBuilder::session_lifecycle()`].
///
/// # Examples
/// ```
/// use actix_web::cookie::time::Duration;
/// use actix_session::SessionMiddleware;
/// use actix_session::config::{PersistentSession, TtlExtensionPolicy};
///
/// const SECS_IN_WEEK: i64 = 60 * 60 * 24 * 7;
///
/// // a session lifecycle with a time-to-live (expiry) of 1 week and default extension policy
/// PersistentSession::default().session_ttl(Duration::seconds(SECS_IN_WEEK));
///
/// // a session lifecycle with the default time-to-live (expiry) and a custom extension policy
/// PersistentSession::default()
/// // this policy causes the session state's TTL to be refreshed on every request
/// .session_ttl_extension_policy(TtlExtensionPolicy::OnEveryRequest);
/// ```
///
/// [persistent]: https://www.whitehatsec.com/glossary/content/persistent-session-cookie /// [persistent]: https://www.whitehatsec.com/glossary/content/persistent-session-cookie
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PersistentSession { pub struct PersistentSession {
@ -113,10 +125,10 @@ pub struct PersistentSession {
impl PersistentSession { impl PersistentSession {
/// Specifies how long the session cookie should live. /// Specifies how long the session cookie should live.
/// ///
/// Defaults to 1 day if left unspecified.
///
/// The session TTL is also used as the TTL for the session state in the storage backend. /// The session TTL is also used as the TTL for the session state in the storage backend.
/// ///
/// Defaults to 1 day.
///
/// A persistent session can live more than the specified TTL if the TTL is extended. /// A persistent session can live more than the specified TTL if the TTL is extended.
/// See [`session_ttl_extension_policy`](Self::session_ttl_extension_policy) for more details. /// See [`session_ttl_extension_policy`](Self::session_ttl_extension_policy) for more details.
pub fn session_ttl(mut self, session_ttl: Duration) -> Self { pub fn session_ttl(mut self, session_ttl: Duration) -> Self {
@ -127,7 +139,7 @@ impl PersistentSession {
/// Determines under what circumstances the TTL of your session should be extended. /// Determines under what circumstances the TTL of your session should be extended.
/// See [`TtlExtensionPolicy`] for more details. /// See [`TtlExtensionPolicy`] for more details.
/// ///
/// Defaults to [`TtlExtensionPolicy::OnStateChanges`] if left unspecified. /// Defaults to [`TtlExtensionPolicy::OnStateChanges`].
pub fn session_ttl_extension_policy( pub fn session_ttl_extension_policy(
mut self, mut self,
ttl_extension_policy: TtlExtensionPolicy, ttl_extension_policy: TtlExtensionPolicy,
@ -148,23 +160,23 @@ impl Default for PersistentSession {
/// Configuration for which events should trigger an extension of the time-to-live for your session. /// Configuration for which events should trigger an extension of the time-to-live for your session.
/// ///
/// If you are using a [`BrowserSession`], `TtlExtensionPolicy` controls how often the TTL of /// If you are using a [`BrowserSession`], `TtlExtensionPolicy` controls how often the TTL of the
/// the session state should be refreshed. The browser is in control of the lifecycle of the /// session state should be refreshed. The browser is in control of the lifecycle of the session
/// session cookie. /// cookie.
/// ///
/// If you are using a [`PersistentSession`], `TtlExtensionPolicy` controls both the expiration /// If you are using a [`PersistentSession`], `TtlExtensionPolicy` controls both the expiration of
/// of the session cookie and the TTL of the session state. /// the session cookie and the TTL of the session state on the storage backend.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[non_exhaustive] #[non_exhaustive]
pub enum TtlExtensionPolicy { pub enum TtlExtensionPolicy {
/// The TTL is refreshed every time the server receives a request associated with a session. /// The TTL is refreshed every time the server receives a request associated with a session.
/// ///
/// # Performance impact /// # Performance impact
/// Refreshing the TTL on every request is not free. /// Refreshing the TTL on every request is not free. It implies a refresh of the TTL on the
/// It implies a refresh of the TTL on the session state. This translates into a request over /// session state. This translates into a request over the network if you are using a remote
/// the network if you are using a remote system as storage backend (e.g. Redis). /// system as storage backend (e.g. Redis). This impacts both the total load on your storage
/// This impacts both the total load on your storage backend (i.e. number of /// backend (i.e. number of queries it has to handle) and the latency of the requests served by
/// queries it has to handle) and the latency of the requests served by your server. /// your server.
OnEveryRequest, OnEveryRequest,
/// The TTL is refreshed every time the session state changes or the session key is renewed. /// The TTL is refreshed every time the session state changes or the session key is renewed.
@ -197,8 +209,7 @@ pub(crate) const fn default_ttl_extension_policy() -> TtlExtensionPolicy {
TtlExtensionPolicy::OnStateChanges TtlExtensionPolicy::OnStateChanges
} }
/// A fluent builder to construct a [`SessionMiddleware`] instance with custom configuration /// A fluent, customized [`SessionMiddleware`] builder.
/// parameters.
#[must_use] #[must_use]
pub struct SessionMiddlewareBuilder<Store: SessionStore> { pub struct SessionMiddlewareBuilder<Store: SessionStore> {
storage_backend: Store, storage_backend: Store,
@ -236,6 +247,22 @@ impl<Store: SessionStore> SessionMiddlewareBuilder<Store> {
/// Check out [`SessionLifecycle`]'s documentation for more details on the available options. /// Check out [`SessionLifecycle`]'s documentation for more details on the available options.
/// ///
/// Default is [`SessionLifecycle::BrowserSession`]. /// Default is [`SessionLifecycle::BrowserSession`].
///
/// # Examples
/// ```
/// use actix_web::cookie::{Key, time::Duration};
/// use actix_session::{SessionMiddleware, config::PersistentSession};
/// use actix_session::storage::CookieSessionStore;
///
/// const SECS_IN_WEEK: i64 = 60 * 60 * 24 * 7;
///
/// // creates a session middleware with a time-to-live (expiry) of 1 week
/// SessionMiddleware::builder(CookieSessionStore::default(), Key::from(&[0; 64]))
/// .session_lifecycle(
/// PersistentSession::default().session_ttl(Duration::seconds(SECS_IN_WEEK))
/// )
/// .build();
/// ```
pub fn session_lifecycle<S: Into<SessionLifecycle>>(mut self, session_lifecycle: S) -> Self { pub fn session_lifecycle<S: Into<SessionLifecycle>>(mut self, session_lifecycle: S) -> Self {
match session_lifecycle.into() { match session_lifecycle.into() {
SessionLifecycle::BrowserSession(BrowserSession { SessionLifecycle::BrowserSession(BrowserSession {

View File

@ -35,6 +35,16 @@ use crate::{
/// [`SessionStore`]); /// [`SessionStore`]);
/// - a secret key, to sign or encrypt the content of client-side session cookie. /// - a secret key, to sign or encrypt the content of client-side session cookie.
/// ///
/// # How did we choose defaults?
/// You should not regret adding `actix-session` to your dependencies and going to production using
/// the default configuration. That is why, when in doubt, we opt to use the most secure option for
/// each configuration parameter.
///
/// We expose knobs to change the default to suit your needs—i.e., if you know what you are doing,
/// we will not stop you. But being a subject-matter expert should not be a requirement to deploy
/// reasonably secure implementation of sessions.
///
/// # Examples
/// ```no_run /// ```no_run
/// use actix_web::{web, App, HttpServer, HttpResponse, Error}; /// use actix_web::{web, App, HttpServer, HttpResponse, Error};
/// use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore}; /// use actix_session::{Session, SessionMiddleware, storage::RedisActorSessionStore};
@ -103,16 +113,6 @@ use crate::{
/// .await /// .await
/// } /// }
/// ``` /// ```
///
/// ## How did we choose defaults?
///
/// You should not regret adding `actix-session` to your dependencies and going to production using
/// the default configuration. That is why, when in doubt, we opt to use the most secure option for
/// each configuration parameter.
///
/// We expose knobs to change the default to suit your needs—i.e., if you know what you are doing,
/// we will not stop you. But being a subject-matter expert should not be a requirement to deploy
/// reasonably secure implementation of sessions.
#[derive(Clone)] #[derive(Clone)]
pub struct SessionMiddleware<Store: SessionStore> { pub struct SessionMiddleware<Store: SessionStore> {
storage_backend: Rc<Store>, storage_backend: Rc<Store>,
@ -125,7 +125,7 @@ impl<Store: SessionStore> SessionMiddleware<Store> {
/// ///
/// To create a new instance of [`SessionMiddleware`] you need to provide: /// To create a new instance of [`SessionMiddleware`] you need to provide:
/// - an instance of the session storage backend you wish to use (i.e. an implementation of /// - an instance of the session storage backend you wish to use (i.e. an implementation of
/// [`SessionStore]); /// [`SessionStore`]);
/// - a secret key, to sign or encrypt the content of client-side session cookie. /// - a secret key, to sign or encrypt the content of client-side session cookie.
pub fn new(store: Store, key: Key) -> Self { pub fn new(store: Store, key: Key) -> Self {
Self::builder(store, key).build() Self::builder(store, key).build()
@ -135,7 +135,7 @@ impl<Store: SessionStore> SessionMiddleware<Store> {
/// ///
/// It takes as input the two required inputs to create a new instance of [`SessionMiddleware`]: /// It takes as input the two required inputs to create a new instance of [`SessionMiddleware`]:
/// - an instance of the session storage backend you wish to use (i.e. an implementation of /// - an instance of the session storage backend you wish to use (i.e. an implementation of
/// [`SessionStore]); /// [`SessionStore`]);
/// - a secret key, to sign or encrypt the content of client-side session cookie. /// - a secret key, to sign or encrypt the content of client-side session cookie.
pub fn builder(store: Store, key: Key) -> SessionMiddlewareBuilder<Store> { pub fn builder(store: Store, key: Key) -> SessionMiddlewareBuilder<Store> {
SessionMiddlewareBuilder::new(store, config::default_configuration(key)) SessionMiddlewareBuilder::new(store, config::default_configuration(key))