7 个不稳定版本
0.4.4 | 2024 年 4 月 7 日 |
---|---|
0.4.3 | 2024 年 1 月 2 日 |
0.4.2 | 2023 年 5 月 11 日 |
0.4.1 | 2023 年 3 月 30 日 |
0.1.0 | 2021 年 6 月 7 日 |
#16 in #trillium
464 个月下载量
87KB
1K SLoC
欢迎来到 Trillium!
📖 指南 📖
指南提供了架构概述和 Trillium 库之间的连接。
📑 Rustdocs 📑
rustdocs 代表了解 Trillium 的各个库及其特定接口的最佳方式。
法律
许可为以下之一
- Apache 许可证 2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
除非您明确声明,否则您提交给工作的任何贡献,根据 Apache-2.0 许可证的定义,应作为上述双重许可,不得附加任何额外条款或条件。
lib.rs
:
Trillium 会话
Trillium 会话建立在 async-session
之上。
会话允许 trillium 在浏览器会话中安全地附加数据,以便在后续访问中检索和修改这些数据。会话数据通常仅在浏览器会话期间保留。
Trillium 的会话实现默认提供访客会话,这意味着所有对启用会话的 trillium 主机的 Web 请求都会附加一个 Cookie,无论该客户端的会话中是否已存储任何内容。
存储
尽管这个crate提供了两个捆绑的会话存储,但强烈建议 trillium 应用程序使用外部数据存储支持的会话存储。有关当前可用的会话存储列表,请参阅 async-session 的文档。
安全
尽管每个会话存储可能具有不同的安全影响,但 trillium 会话系统的一般方法如下:在每个请求上,trillium 检查处理程序上可配置为 cookie_name
的 Cookie。
如果未找到 Cookie
通过密码学随机算法生成cookie值。在出站响应中设置cookie,并使用从创建SessionHandler时提供的secret
派生的HKDF密钥进行签名。可配置的会话存储使用cookie值的SHA256摘要存储会话,并可能包括过期时间。
如果找到cookie
使用从HKDF派生的签名密钥验证cookie值的签名。如果验证成功,则将其传递给会话存储以检索会话。对于大多数会话存储,这将涉及获取cookie值的SHA256摘要,并根据该摘要从外部数据存储中检索序列化的会话。
过期时间
除了在会话cookie上设置过期时间外,trillium会话还包括相同的过期时间在其序列化格式中。如果攻击者能够篡改cookie的过期时间,trillium会话在使用之前仍会检查包含的会话的过期时间。
如果上述过程中的任何操作出现问题
如果上述会话检索过程中出现任何失败,将为请求生成一个新的空会话,然后像往常一样通过应用程序。
过时/已过期会话清理
除了cookie存储以外的任何会话存储都会积累过时会话。尽管trillium会话处理程序确保它们不会被用作有效会话,但对于大多数会话存储来说,如果需要,调用会话存储的清理是trillium应用程序的责任。
use trillium::Conn;
use trillium_cookies::{CookiesHandler, cookie::Cookie};
use trillium_sessions::{MemoryStore, SessionConnExt, SessionHandler};
let session_secret = std::env::var("TRILLIUM_SESSION_SECRET").unwrap();
let handler = (
CookiesHandler::new(),
SessionHandler::new(MemoryStore::new(), session_secret.as_bytes()),
|conn: Conn| async move {
let count: usize = conn.session().get("count").unwrap_or_default();
conn.with_session("count", count + 1)
.ok(format!("count: {}", count))
},
);
use trillium_testing::prelude::*;
let mut conn = get("/").on(&handler);
assert_ok!(&mut conn, "count: 0");
let set_cookie_header = conn.response_headers().get_str("set-cookie").unwrap();
let cookie = Cookie::parse_encoded(set_cookie_header).unwrap();
let make_request = || get("/")
.with_request_header("cookie", format!("{}={}", cookie.name(), cookie.value()))
.on(&handler);
assert_ok!(make_request(), "count: 1");
assert_ok!(make_request(), "count: 2");
assert_ok!(make_request(), "count: 3");
assert_ok!(make_request(), "count: 4");
依赖项
~11-18MB
~311K SLoC