这是由 Sa-Token 社区成员发起的一个项目:sa-token-rust —— sa-token 的 rust 版本。
对 rust 熟悉的同学速来围观啦。
目前该仓库处于起步阶段,不过已经有不错的完成度了。源码注释也是中文的哦。
一个轻量级、高性能的 Rust 认证授权框架:
✨ 特性
- 🚀 多框架支持: Axum, Actix-web, Poem, Rocket, Warp
- 🔐 完整的认证: 登录、登出、Token 验证、Session 管理
- 🛡️ 细粒度授权: 基于权限和角色的访问控制
- 💾 灵活存储: 内存、Redis 和数据库存储后端
- 🎯 易于使用: 过程宏和工具类简化集成
- ⚡ 高性能: 零拷贝设计,支持 async/await
- 🔧 高度可配置: Token 超时、Cookie 选项、自定义 Token 名称
📦 架构
sa-token-rust/
├── sa-token-core/ # 核心库(Token、Session、Manager)
├── sa-token-adapter/ # 适配器接口(Storage、Request/Response)
├── sa-token-macro/ # 过程宏(#[sa_check_login] 等)
├── sa-token-storage-memory/ # 内存存储实现
├── sa-token-storage-redis/ # Redis 存储实现
├── sa-token-storage-database/ # 数据库存储实现(占位符)
├── sa-token-plugin-axum/ # Axum 框架集成
├── sa-token-plugin-actix-web/ # Actix-web 框架集成
├── sa-token-plugin-poem/ # Poem 框架集成
├── sa-token-plugin-rocket/ # Rocket 框架集成
├── sa-token-plugin-warp/ # Warp 框架集成
└── examples/ # 示例项目
├── axum-full-example/ # 完整 Axum 示例
└── poem-full-example/ # 完整 Poem 示例- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
🎯 核心组件
1. sa-token-core
核心认证授权逻辑:
- SaTokenManager: Token 和 Session 操作的主管理器
- StpUtil: 提供简化 API 的工具类 (文档)
- Token 生成、验证和刷新
- Session 管理
- 权限和角色检查
2. sa-token-adapter
框架集成的抽象层:
- SaStorage: Token 和 Session 的存储接口
- SaRequest / SaResponse: 请求/响应抽象
3. sa-token-macro
用于注解式认证的过程宏:
#[sa_check_login]: 要求登录#[sa_check_permission("user:list")]: 检查权限 (匹配规则)#[sa_check_role("admin")]: 检查角色#[sa_check_permissions_and(...)]: 检查多个权限(AND)#[sa_check_permissions_or(...)]: 检查多个权限(OR)#[sa_ignore]: 跳过认证
4. Web 框架插件
所有插件都提供:
- 使用 Builder 模式的状态管理
- 双重中间件(基础 + 强制登录)
- 三种提取器(必须、可选、LoginId)
- 请求/响应适配器
- 从 Header/Cookie/Query 提取 Token
- Bearer Token 支持
🚀 快速开始
1. 添加依赖
[dependencies]
sa-token-core = "0.1"
sa-token-storage-memory = "0.1"
sa-token-plugin-axum = "0.1" # 选择你的框架
tokio = { version = "1", features = ["full"] }
axum = "0.7"- 1
- 2
- 3
- 4
- 5
- 6
2. 初始化 sa-token
use sa_token_core::StpUtil;
use sa_token_plugin_axum::SaTokenState;
use sa_token_storage_memory::MemoryStorage;
use std::sync::Arc;
#[tokio::main]
async fn main() {
// 创建状态(StpUtil 会自动初始化)
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.token_name("Authorization")
.timeout(86400) // 24 小时
.build();
// StpUtil 已就绪,可以直接使用!
// 你的应用代码...
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
3. 用户登录
use sa_token_core::StpUtil;
// 用户登录
let token = StpUtil::login("user_id_10001").await?;
println!("Token: {}", token.value());
// 设置权限和角色
StpUtil::set_permissions(
"user_id_10001",
vec!["user:list".to_string(), "user:add".to_string()]
).await?;
StpUtil::set_roles(
"user_id_10001",
vec!["admin".to_string()]
).await?;- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
4. 检查认证(Axum 示例)
use axum::{Router, routing::get};
use sa_token_plugin_axum::{SaTokenMiddleware, LoginIdExtractor};
async fn user_info(LoginIdExtractor(login_id): LoginIdExtractor) -> String {
format!("当前用户: {}", login_id)
}
async fn admin_panel(login_id: LoginIdExtractor) -> String {
// 检查权限
if !StpUtil::has_permission(&login_id.0, "admin:panel").await {
return "无权限".to_string();
}
format!("欢迎管理员: {}", login_id.0)
}
let app = Router::new()
.route("/user/info", get(user_info))
.route("/admin/panel", get(admin_panel))
.layer(SaTokenMiddleware::new(state));- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
5. 使用过程宏
use sa_token_macro::*;
#[sa_check_login]
async fn protected_route() -> &'static str {
"此路由需要登录"
}
#[sa_check_permission("user:delete")]
async fn delete_user(user_id: String) -> &'static str {
"用户已删除"
}
#[sa_check_role("admin")]
async fn admin_only() -> &'static str {
"仅管理员可见内容"
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
📚 框架集成示例
Axum
use axum::{Router, routing::{get, post}};
use sa_token_plugin_axum::{SaTokenState, SaTokenMiddleware, LoginIdExtractor};
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.build();
let app = Router::new()
.route("/user/info", get(user_info))
.layer(SaTokenMiddleware::new(state));- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Actix-web
use actix_web::{App, HttpServer, web};
use sa_token_plugin_actix_web::{SaTokenState, SaTokenMiddleware, LoginIdExtractor};
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.build();
HttpServer::new(move || {
App::new()
.app_data(state.clone())
.wrap(SaTokenMiddleware::new((*state).clone()))
.route("/user/info", web::get().to(user_info))
})
.bind("127.0.0.1:8080")?
.run()
.await- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
Poem
use poem::{Route, Server};
use sa_token_plugin_poem::{SaTokenState, SaTokenMiddleware, LoginIdExtractor};
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.build();
let app = Route::new()
.at("/user/info", poem::get(user_info))
.with(SaTokenMiddleware::new(state));
Server::new(TcpListener::bind("127.0.0.1:8080"))
.run(app)
.await- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
Rocket
use rocket::{launch, get, routes};
use sa_token_plugin_rocket::{SaTokenState, SaTokenFairing, LoginIdGuard};
#[get("/user/info")]
fn user_info(login_id: LoginIdGuard) -> String {
format!("用户: {}", login_id.0)
}
#[launch]
fn rocket() -> _ {
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.build();
rocket::build()
.attach(SaTokenFairing::new(state))
.mount("/", routes![user_info])
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
Warp
use warp::Filter;
use sa_token_plugin_warp::{SaTokenState, sa_token_filter};
let state = SaTokenState::builder()
.storage(Arc::new(MemoryStorage::new()))
.build();
let routes = warp::path("user")
.and(warp::path("info"))
.and(sa_token_filter(state))
.map(|token_data| {
format!("用户信息")
});
warp::serve(routes)
.run(([127, 0, 0, 1], 8080))
.await;- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
开源地址
感兴趣的同学可以来关注一波:
https://github.com/llc-993/sa-token-rust
鲁公网安备37011202002956号