Skip to main content

alun_web/middleware/
mod.rs

1//! Alun 请求中间件模块
2//!
3//! 按职责拆分为多个子模块:
4//! | 模块               | 功能                 |
5//! |-------------------|---------------------|
6//! | [request_id]      | 请求 ID 生成/注入     |
7//! | [auth]            | JWT Bearer Token 认证 |
8//! | [role]            | 角色校验              |
9//! | [permission]      | 权限标识校验          |
10//! | [permission_check]| 路径权限规则校验       |
11//! | [request_log]     | 请求访问日志(tracing 输出) |
12//! | [rate_limit]      | IP 滑动窗口限流       |
13//! | [security_headers]| 安全响应头注入         |
14//! | [nonce]           | Nonce 防重放(按需)    |
15//! | [idempotency]     | 幂等键(按需)         |
16
17pub mod request_id;
18pub mod auth;
19pub mod role;
20pub mod permission;
21pub mod permission_check;
22pub mod request_log;
23pub mod rate_limit;
24pub mod security_headers;
25#[cfg(feature = "cache")]
26pub mod nonce;
27#[cfg(feature = "cache")]
28pub mod idempotency;
29
30pub use request_id::{RequestIdLayer, RequestIdService};
31pub use auth::{AuthLayer, AuthService};
32pub use role::{RequireRoleLayer, RequireRoleService};
33pub use permission::{RequirePermissionLayer, RequirePermissionService};
34pub use permission_check::{PermissionCheckLayer, PermissionRule, PermissionCheckService};
35pub use request_log::{RequestLogLayer, RequestLogService};
36pub use rate_limit::{RateLimitLayer, IpWindow, RateLimitService};
37pub use security_headers::{SecurityHeadersLayer, SecurityHeadersService};
38#[cfg(feature = "cache")]
39pub use nonce::{NonceLayer, NonceService};
40#[cfg(feature = "cache")]
41pub use idempotency::{IdempotencyLayer, IdempotencyService};
42
43/// Token 类型
44#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
45pub enum TokenType {
46    /// 访问 Token
47    #[serde(rename = "access")]
48    Access,
49    /// 刷新 Token
50    #[serde(rename = "refresh")]
51    Refresh,
52}
53
54/// JWT Token 声明(与 jsonwebtoken 配合使用)
55///
56/// 由 AuthLayer 中间件验证后注入到 `request.extensions`,
57/// 业务代码可通过 `Extension<AuthClaims>` 提取。
58#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
59pub struct TokenClaims {
60    /// JWT 唯一标识(jti),用于 Token 黑名单/撤销机制
61    #[serde(default)]
62    pub jti: Option<String>,
63    /// 用户 ID(subject)
64    pub sub: String,
65    /// 用户名
66    #[serde(default, skip_serializing_if = "Option::is_none")]
67    pub username: Option<String>,
68    /// 角色列表(如 ["admin", "user"])
69    #[serde(default, skip_serializing_if = "Vec::is_empty")]
70    pub roles: Vec<String>,
71    /// 权限列表(如 ["user:read", "user:write"])
72    #[serde(default, skip_serializing_if = "Vec::is_empty")]
73    pub permissions: Vec<String>,
74    /// Token 类型
75    #[serde(default)]
76    pub token_type: Option<TokenType>,
77    /// 过期时间(Unix 时间戳,秒)
78    pub exp: usize,
79    /// 签发时间(Unix 时间戳,秒)
80    #[serde(default)]
81    pub iat: usize,
82}
83
84impl TokenClaims {
85    /// 获取用户 ID
86    pub fn user_id(&self) -> &str {
87        &self.sub
88    }
89
90    /// 是否拥有指定角色
91    pub fn has_role(&self, role: &str) -> bool {
92        self.roles.iter().any(|r| r == role)
93    }
94
95    /// 是否拥有任一角色
96    pub fn has_any_role(&self, roles: &[&str]) -> bool {
97        roles.iter().any(|r| self.has_role(r))
98    }
99
100    /// 是否拥有所有角色
101    pub fn has_all_roles(&self, roles: &[&str]) -> bool {
102        roles.iter().all(|r| self.has_role(r))
103    }
104
105    /// 是否拥有指定权限
106    ///
107    /// 若 claims 中包含 `*` 或 `*:*:*` 通配权限,则匹配任意权限。
108    pub fn has_permission(&self, permission: &str) -> bool {
109        self.is_super_admin() || self.permissions.iter().any(|p| p == permission)
110    }
111
112    /// 是否拥有任一权限
113    pub fn has_any_permission(&self, permissions: &[&str]) -> bool {
114        self.is_super_admin() || permissions.iter().any(|p| self.has_permission(p))
115    }
116
117    /// 是否为超级管理员(拥有 `*` 或 `*:*:*` 通配权限)
118    pub fn is_super_admin(&self) -> bool {
119        self.permissions.iter().any(|p| p == "*" || p == "*:*:*")
120    }
121}
122
123/// 已认证用户的 ID(从 JWT Token 中提取)
124#[derive(Clone, Debug)]
125pub struct UserId(pub String);
126
127/// JWT 认证声明(挂载在 `request.extensions` 中)
128#[derive(Clone, Debug)]
129pub struct AuthClaims(pub TokenClaims);