32个版本 (11个破坏性版本)

0.12.3 2024年8月15日
0.12.2 2024年4月14日
0.12.1 2024年3月31日
0.8.2 2023年12月24日
0.7.0 2023年11月27日

#36 in 异步

Download history 3111/week @ 2024-05-03 3398/week @ 2024-05-10 3459/week @ 2024-05-17 4199/week @ 2024-05-24 4454/week @ 2024-05-31 3753/week @ 2024-06-07 4691/week @ 2024-06-14 19414/week @ 2024-06-21 18887/week @ 2024-06-28 12598/week @ 2024-07-05 11941/week @ 2024-07-12 10152/week @ 2024-07-19 11769/week @ 2024-07-26 11010/week @ 2024-08-02 13109/week @ 2024-08-09 13313/week @ 2024-08-16

51,366 每月下载次数
用于 23 个crate (22直接)

MIT 许可证

120KB
1.5K SLoC

tower-sessions

🥠 将会话作为 `tower` 和 `axum` 中间件。

🎨 概述

此crate提供会话,与站点访问者关联的键值对,作为 tower 中间件。

它提供

  • 可插拔存储后端: 通过实现 SessionStore 特性,简单地使用自己的后端,完全解耦会话与其存储。
  • 最小开销: 只有在实际使用时,会话才会从其支持存储加载,例如在使用的处理程序中。这意味着此中间件可以以最小的开销安装到您的路由图中任何位置。
  • axum 提取器用于 Session 使用 axum 构建的应用程序可以直接在其处理程序中使用 Session 作为提取器。这使得使用会话与在处理程序中包含 Session 一样简单。
  • 简单的键值接口: 会话提供支持本地Rust类型的键值接口。只要这些类型是 Serialize 并且可以转换为JSON,插入、获取和删除任何值都很容易。
  • 强类型会话: 强类型保证可以轻松地建立在基础键值接口之上。

此crate的会话实现灵感来源于Django会话中间件,并提供这些语义的转义。

会话存储

会话数据持久性由用户提供的实现 SessionStore 的类型管理。这意味着应用程序可以也应该实现会话存储以满足其特定需求。

尽管如此,已经存在许多会话存储实现,可能是有用的起点。

Crate Persistent 描述
tower-sessions-dynamodb-store Amazon DynamoDB 会话存储
tower-sessions-firestore-store Firestore 会话存储
tower-sessions-libsql-store libSQL 会话存储
tower-sessions-mongodb-store MongoDB 会话存储
tower-sessions-moka-store Moka 会话存储
tower-sessions-redis-store 通过 fred 的 Redis 会话存储
tower-sessions-rorm-store rorm 提供的 SQLite、Postgres 和 MySQL 会话存储
tower-sessions-rusqlite-store Rusqlite 会话存储
tower-sessions-sled-store Sled 会话存储
tower-sessions-sqlx-store SQLite、Postgres 和 MySQL 会话存储
tower-sessions-surrealdb-store SurrealDB 会话存储

要添加存储?请提交一个包含它的 PR。

用户会话管理

为了便于身份验证和授权,我们在该crate的基础上构建了 axum-login。如果您正在寻找一个通用的身份验证解决方案,请查看它。

📦 安装

要在项目中使用此crate,请将以下内容添加到您的 Cargo.toml 文件中

[dependencies]
tower-sessions = "0.12.3"

🤸 使用

axum 示例

use std::net::SocketAddr;

use axum::{response::IntoResponse, routing::get, Router};
use serde::{Deserialize, Serialize};
use time::Duration;
use tower_sessions::{Expiry, MemoryStore, Session, SessionManagerLayer};

const COUNTER_KEY: &str = "counter";

#[derive(Default, Deserialize, Serialize)]
struct Counter(usize);

async fn handler(session: Session) -> impl IntoResponse {
    let counter: Counter = session.get(COUNTER_KEY).await.unwrap().unwrap_or_default();
    session.insert(COUNTER_KEY, counter.0 + 1).await.unwrap();
    format!("Current count: {}", counter.0)
}

#[tokio::main]
async fn main() {
    let session_store = MemoryStore::default();
    let session_layer = SessionManagerLayer::new(session_store)
        .with_secure(false)
        .with_expiry(Expiry::OnInactivity(Duration::seconds(10)));

    let app = Router::new().route("/", get(handler)).layer(session_layer);

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
    axum::serve(listener, app.into_make_service())
        .await
        .unwrap();
}

您可以在 此处 找到这个示例,以及其他示例项目在 示例目录 中。

[!NOTE] 更多使用信息,请参阅 crate 文档

🦺 安全性

此crate使用 #![forbid(unsafe_code)] 来确保所有内容都在100%安全的Rust中实现。

🛟 获取帮助

我们提供了一些 示例 来帮助您入门。您也可以 发起一个讨论 并提出您可能有的其他问题。

👯 贡献

我们感谢所有类型的贡献,谢谢!

依赖项

~6–14MB
~156K SLoC