بنقرة واحدة
rust-xacml
策略引擎、权限决策、RBAC、策略模式、责任链
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
策略引擎、权限决策、RBAC、策略模式、责任链
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Actor model expert covering message passing, state isolation, supervision trees, deadlock prevention, fault tolerance, Actix framework, and Erlang-style concurrency patterns.
Rust anti-patterns and common mistakes expert. Handles code review issues with clone abuse, unwrap in production, String misuse, index loops, and refactoring guidance.
Advanced async patterns expert covering Stream implementation, zero-copy buffers, tokio::spawn lifetimes, plugin system scheduling, tonic streaming, and async lifetime management.
Advanced async patterns expert. Handles Stream processing, backpressure control, select/join operations, cancellation, Future trait implementation, and async runtime optimization.
Authentication and authorization expert covering JWT, API keys, OAuth, RBAC, password hashing, distributed token storage, and session management patterns.
Caching and distributed storage expert covering Redis, connection pools, TTL strategies, cache patterns (Cache-Aside, Write-Through), invalidation, and performance optimization.
استنادا إلى تصنيف SOC المهني
| name | rust-xacml |
| description | 策略引擎、权限决策、RBAC、策略模式、责任链--- |
//! 策略评估器
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// 请求上下文
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RequestContext {
pub subject: Subject, // 主体
pub resource: Resource, // 资源
pub action: String, // 操作
pub environment: HashMap<String, String>, // 环境
}
/// 主体
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Subject {
pub id: String,
pub roles: Vec<String>,
pub attributes: HashMap<String, String>,
}
/// 资源
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Resource {
pub id: String,
pub r#type: String,
pub attributes: HashMap<String, String>,
}
/// 决策结果
#[derive(Debug, Clone, PartialEq)]
pub enum Decision {
Permit,
Deny,
NotApplicable,
Indeterminate(String),
}
/// 策略定义
#[derive(Debug, Clone)]
pub struct Policy {
pub id: String,
pub target: PolicyTarget,
pub rules: Vec<Rule>,
pub combining_algorithm: CombiningAlgorithm,
}
/// 策略目标(匹配条件)
#[)]
pub struct PolicyTarget {
pubderive(Debug, Clone subjects: Vec<Vec<String>>, // 角色组合
pub resources: Vec<String>,
pub actions: Vec<String>,
}
/// 访问规则
#[derive(Debug, Clone)]
pub struct Rule {
pub id: String,
pub effect: RuleEffect,
pub condition: Option<Box<dyn Fn(&RequestContext) -> bool + Send>>,
}
#[derive(Debug, Clone, Copy)]
pub enum RuleEffect {
Permit,
Deny,
}
/// 策略组合算法
#[derive(Debug, Clone, Copy)]
pub enum CombiningAlgorithm {
DenyOverrides, // Deny 优先
PermitOverrides, // Permit 优先
FirstApplicable, // 首个适用
OnlyOneApplicable, // 仅一个适用
}
/// 策略评估器
pub struct PolicyEvaluator {
policies: Vec<Policy>,
}
impl PolicyEvaluator {
pub fn new(policies: Vec<Policy>) -> Self {
Self { policies }
}
/// 评估请求
pub fn evaluate(&self, context: &RequestContext) -> Decision {
let mut applicable_policies: Vec<&Policy> = self.policies
.iter()
.filter(|p| self.is_target_matched(p, context))
.collect();
if applicable_policies.is_empty() {
return Decision::NotApplicable;
}
// 根据组合算法计算最终决策
match applicable_policies.first().map(|p| p.combining_algorithm).unwrap_or(CombiningAlgorithm::FirstApplicable) {
CombiningAlgorithm::DenyOverrides => self.deny_overrides(&applicable_policies, context),
CombiningAlgorithm::PermitOverrides => self.permit_overrides(&applicable_policies, context),
CombiningAlgorithm::FirstApplicable => self.first_applicable(&applicable_policies, context),
CombiningAlgorithm::OnlyOneApplicable => {
if applicable_policies.len() == 1 {
self.evaluate_policy(applicable_policies[0], context)
} else {
Decision::Indeterminate("Multiple applicable policies".to_string())
}
}
}
}
fn is_target_matched(&self, policy: &Policy, context: &RequestContext) -> bool {
// 检查 Subjects
let subject_matches = policy.target.subjects.is_empty() ||
policy.target.subjects.iter().any(|roles| {
roles.iter().all(|r| context.subject.roles.contains(r))
});
// 检查 Resources
let resource_matches = policy.target.resources.is_empty() ||
policy.target.resources.contains(&context.resource.r#type);
// 检查 Actions
let action_matches = policy.target.actions.is_empty() ||
policy.target.actions.contains(&context.action);
subject_matches && resource_matches && action_matches
}
fn deny_overrides(&self, policies: &[&Policy], context: &RequestContext) -> Decision {
let mut has_error = false;
let mut error_msg = String::new();
for policy in policies {
match self.evaluate_policy(policy, context) {
Decision::Deny => return Decision::Deny,
Decision::Indeterminate(msg) => {
has_error = true;
error_msg = msg;
}
_ => {}
}
}
if has_error {
Decision::Indeterminate(error_msg)
} else {
Decision::Permit
}
}
fn permit_overrides(&self, policies: &[&Policy], context: &RequestContext) -> Decision {
let mut has_error = false;
let mut error_msg = String::new();
for policy in policies {
match self.evaluate_policy(policy, context) {
Decision::Permit => return Decision::Permit,
Decision::Indeterminate(msg) => {
has_error = true;
error_msg = msg;
}
_ => {}
}
}
if has_error {
Decision::Indeterminate(error_msg)
} else {
Decision::Deny
}
}
fn first_applicable(&self, policies: &[&Policy], context: &RequestContext) -> Decision {
for policy in policies {
let decision = self.evaluate_policy(policy, context);
if decision != Decision::NotApplicable {
return decision;
}
}
Decision::Deny
}
fn evaluate_policy(&self, policy: &Policy, context: &RequestContext) -> Decision {
for rule in &policy.rules {
if let Some(ref condition) = rule.condition {
if !condition(context) {
continue;
}
}
return match rule.effect {
RuleEffect::Permit => Decision::Permit,
RuleEffect::Deny => Decision::Deny,
};
}
Decision::NotApplicable
}
}
//! RBAC 权限检查
use std::collections::HashMap;
/// RBAC 配置
#[derive(Debug, Clone)]
pub struct RbacConfig {
/// 角色层级
pub role_hierarchy: HashMap<String, Vec<String>>,
/// 角色权限映射
pub role_permissions: HashMap<String, Vec<String>>,
/// 权限定义
pub permissions: HashMap<String, PermissionDef>,
}
/// 权限定义
#[derive(Debug, Clone)]
pub struct PermissionDef {
pub resource: String,
pub actions: Vec<String>,
}
/// RBAC 检查器
pub struct RbacChecker {
config: RbacConfig,
}
impl RbacChecker {
pub fn new(config: RbacConfig) -> Self {
Self { config }
}
/// 检查用户是否有权限
pub fn check_permission(
&self,
user_roles: &[String],
resource: &str,
action: &str,
) -> bool {
// 获取所有继承的角色
let all_roles = self.expand_roles(user_roles);
// 检查是否有权限
for role in &all_roles {
if let Some(perms) = self.config.role_permissions.get(role) {
for perm_id in perms {
if let Some(perm) = self.config.permissions.get(perm_id) {
if perm.resource == resource && perm.actions.contains(&action) {
return true;
}
}
}
}
}
false
}
/// 展开角色层级
fn expand_roles(&self, roles: &[String]) -> Vec<String> {
let mut expanded = Vec::new();
let mut visited = std::collections::HashSet::new();
let mut queue = Vec::new();
for role in roles {
if !visited.contains(role) {
queue.push(role.clone());
visited.insert(role.clone());
}
}
while let Some(role) = queue.pop() {
expanded.push(role.clone());
if let Some(parents) = self.config.role_hierarchy.get(&role) {
for parent in parents {
if !visited.contains(parent) {
visited.insert(parent.clone());
queue.push(parent.clone());
}
}
}
}
expanded
}
/// 获取用户的所有权限
pub fn get_user_permissions(&self, user_roles: &[String]) -> Vec<String> {
let all_roles = self.expand_roles(user_roles);
let mut permissions = std::collections::HashSet::new();
for role in &all_roles {
if let Some(role_perms) = self.config.role_permissions.get(role) {
for perm in role_perms {
permissions.insert(perm.clone());
}
}
}
permissions.into_iter().collect()
}
}
//! 策略缓存
use crate::{Policy, PolicyEvaluator};
use std::sync::Arc;
use tokio::sync::RwLock;
use std::time::{Duration, Instant};
/// 缓存配置
#[derive(Debug, Clone)]
pub struct PolicyCacheConfig {
pub ttl: Duration,
pub max_size: usize,
}
/// 缓存条目
struct CacheEntry {
policy: Policy,
inserted_at: Instant,
}
/// 策略缓存
pub struct PolicyCache {
config: PolicyCacheConfig,
cache: Arc<RwLock<HashMap<String, CacheEntry>>>,
}
impl PolicyCache {
pub fn new(config: PolicyCacheConfig) -> Self {
Self {
config,
cache: Arc::new(RwLock::new(HashMap::new())),
}
}
/// 获取策略
pub async fn get(&self, policy_id: &str) -> Option<Policy> {
let cache = self.cache.read().await;
cache.get(policy_id).map(|entry| entry.policy.clone())
}
/// 存储策略
pub async fn set(&self, policy: Policy) {
let mut cache = self.cache.write().await;
// 清理过期条目
let now = Instant::now();
cache.retain(|_, v| now.duration_since(v.inserted_at) < self.config.ttl);
// 清理超出大小的条目
if cache.len() >= self.config.max_size {
let to_remove = cache.len() - self.config.max_size + 1;
let keys: Vec<String> = cache.keys().take(to_remove).cloned().collect();
for key in keys {
cache.remove(&key);
}
}
cache.insert(policy.id.clone(), CacheEntry {
policy,
inserted_at: Instant::now(),
});
}
/// 失效策略
pub async fn invalidate(&self, policy_id: &str) {
let mut cache = self.cache.write().await;
cache.remove(policy_id);
}
/// 清理所有
pub async fn clear(&self) {
let mut cache = self.cache.write().await;
cache.clear();
}
}
//! 策略构建器
use crate::{Policy, PolicyTarget, Rule, RuleEffect, CombiningAlgorithm};
/// 策略构建器
pub struct PolicyBuilder {
policy: Policy,
}
impl PolicyBuilder {
pub fn new(id: &str) -> Self {
Self {
policy: Policy {
id: id.to_string(),
target: PolicyTarget {
subjects: Vec::new(),
resources: Vec::new(),
actions: Vec::new(),
},
rules: Vec::new(),
combining_algorithm: CombiningAlgorithm::DenyOverrides,
},
}
}
pub fn with_subject_roles(mut self, roles: &[&str]) -> Self {
self.policy.target.subjects = vec![roles.iter().map(|s| s.to_string()).collect()];
self
}
pub fn with_resource(mut self, resource: &str) -> Self {
self.policy.target.resources = vec![resource.to_string()];
self
}
pub fn with_action(mut self, action: &str) -> Self {
self.policy.target.actions = vec![action.to_string()];
self
}
pub fn add_rule(
mut self,
id: &str,
effect: RuleEffect,
condition: impl Fn(&crate::RequestContext) -> bool + Send + 'static,
) -> Self {
self.policy.rules.push(Rule {
id: id.to_string(),
effect,
condition: Some(Box::new(condition)),
});
self
}
pub fn with_combining_algorithm(mut self, algo: CombiningAlgorithm) -> Self {
self.policy.combining_algorithm = algo;
self
}
pub fn build(self) -> Policy {
self.policy
}
}
/// 使用示例
fn example_policy() -> Policy {
PolicyBuilder::new("read-policy")
.with_subject_roles(&["user", "admin"])
.with_resource("document")
.with_action("read")
.add_rule("own-document", RuleEffect::Permit, |ctx| {
// 自己创建的文档可以读取
ctx.resource.attributes.get("owner") == Some(&ctx.subject.id)
})
.add_rule("public-document", RuleEffect::Permit, |ctx| {
// 公开文档可以读取
ctx.resource.attributes.get("visibility") == Some(&"public".to_string())
})
.with_combining_algorithm(CombiningAlgorithm::DenyOverrides)
.build()
}
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 决策不一致 | 组合算法选择不当 | 根据业务选择合适的算法 |
| 性能差 | 策略过多 | 使用缓存和索引 |
| 权限绕过 | 规则顺序问题 | DenyOverrides 优先 |
rust-auth - 认证授权rust-web - Web 集成rust-cache - 策略缓存rust-performance - 性能优化