3个版本 (重大变更)
新 0.3.0 | 2024年8月20日 |
---|---|
0.2.0 | 2024年8月19日 |
0.1.0 | 2024年8月19日 |
#496 in 密码学
每月 338次下载
28KB
410 行
🏄♂️ 概述
这个crate使用双重提交Cookie模式来减轻CSRF。
工作原理
- 密钥:您提供一个用于签名CSRF令牌的密钥。此密钥通过secstr加密,并在签名和验证过程中仅在内存中以明文形式存储。有关密钥管理的更多信息,请参阅OWASP的加密存储便签。
- 令牌创建:
- 我们通过结合一个唯一的会话标识符和一个加密安全的随机值(使用
rand
crate)生成一个消息。 - 然后我们使用密钥和消息创建一个签名。
- 令牌通过连接签名和消息形成。
- 我们通过结合一个唯一的会话标识符和一个加密安全的随机值(使用
- 令牌存储:
- 服务器以两种方式将令牌发送到客户端
- 作为cookie(由我们处理)。
- 在后续请求的头部(由您处理)。
- 服务器以两种方式将令牌发送到客户端
- 令牌验证:
- 对于每个即将改变状态的传入请求
- 我们从请求头部提取令牌。
- 我们将令牌分成签名和消息。
- 我们使用密钥和消息重新计算签名并比较它们。
- 如果签名有效且令牌与存储在cookie中的值匹配,则允许请求继续。
- 对于每个即将改变状态的传入请求
Cookie
默认情况下,cookie被设置为HTTPOnly
、SameSite: Strict
和Secure
。
📦 安装
[dependencies]
tower-surf = "0.3.0"
🗝️ 使用方法
使用axum
use std::net::SocketAddr;
use axum::{routing::get, Router};
use http::StatusCode;
use tower_surf::{Surf, Token};
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/login", get(login)).route("/logout", get(logout))
.layer(Surf::new("secret-key").secure(false));
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();
}
async fn login(token: Token) -> Result<StatusCode, StatusCode> {
token.set("unique-session-id").map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
Ok(StatusCode::OK)
}
async fn logout(token: Token) -> StatusCode {
token.reset();
StatusCode::OK
}
[!注意] 请参阅示例以获取完整示例。
🥰 感谢
- 我阅读了很多tower-sessions代码库,以了解如何创建一个tower项目。
- tokio社区回答了很多愚蠢的问题。
依赖项
~4-10MB
~101K SLoC