ruxt axum中使用casbin-rs
一、casbin-rs是什么?
casbin-rs是管理端rbac权限框架的rust抽象实现
二、使用步骤
1.引入库
代码如下(示例):
Cargo.toml中引入
casbin = "2.0.9"
2.核心service封装
代码如下(示例):
casbin_service.rs
#[derive(Clone)]
pub struct CasbinVals {
pub uid: String,
pub agency_code: Option<String>,
}
/**
*struct:CasbinService
*desc:casbin 权限处理核心service
*author:String
*email:348040933@qq.com
*/
#[derive(Clone)]
pub struct CasbinService {
pub enforcer: Arc<RwLock<CachedEnforcer>>,
}
impl CasbinService {
/**
sign_in
*method:default
*desc:初始化casbin 上下文 加载model 初始化 CICIAdapter casbin适配器
*author:String
*email:348040933@qq.com
*/
pub async fn default() -> Self {
/*加载模型文件*/
let m = DefaultModel::from_file("cassie_web/auth_config/rbac_with_domains_model.conf")
.await
.unwrap();
info!("casbin模型文件加载完成!");
let config = APPLICATION_CONTEXT.get::<ApplicationConfig>();
//这里是自定义rbatis适配器
//https://gitee.com/stringlxd/cassie_axum/tree/master/cassie_casbin_adapte
let a = CICIAdapter::new(init_rbatis(config).await);
let mut cached_enforcer = CachedEnforcer::new(m, a).await.unwrap();
/* 添加自定义验证方法 */
cached_enforcer.add_function("ciciMatch", cici_match);
info!("casbin init success");
Self {
enforcer: Arc::new(RwLock::new(cached_enforcer)),
}
}
pub async fn new<M: TryIntoModel, A: TryIntoAdapter>(m: M, a: A) -> CasbinResult<Self> {
let enforcer: CachedEnforcer = CachedEnforcer::new(m, a).await?;
Ok(CasbinService {
enforcer: Arc::new(RwLock::new(enforcer)),
})
}
pub fn get_enforcer(&self) -> Arc<RwLock<CachedEnforcer>> {
self.enforcer.clone()
}
pub fn set_enforcer(e: Arc<RwLock<CachedEnforcer>>) -> CasbinService {
CasbinService { enforcer: e }
}
/**
*method:call
*desc:核心验证方法 path ,action ,vals
*author:String
*email:348040933@qq.com
*/
pub async fn call(&self, path: String, action: String, vals: CasbinVals) -> bool {
/*获取验证器*/
let cloned_enforcer = self.get_enforcer();
let uid = vals.uid.clone();
/*获取对应的 用户 用户为空直接返回false*/
if !vals.uid.is_empty() {
/*判断是否是多租户模型*/
let vecs = if let Some(agency_code) = vals.agency_code {
vec![uid, agency_code, path, action]
} else {
vec![uid, path, action]
};
let mut lock = cloned_enforcer.write().await;
match lock.enforce_mut(vecs) {
Ok(true) => {
drop(lock);
true
}
Ok(false) => {
drop(lock);
false
}
Err(_) => {
drop(lock);
false
}
}
} else {
false
}
}
}
//初始化casbin_service
这里只是核心的代码封装
总结
以上只是cassie axum代码里的核心封装
在这里我们使用到的是CachedEnforcer,由于web项目的path
资源验证不可每次都查数据库 所以需要用到缓存
项目启动时加载
pub async fn init_casbin() {
APPLICATION_CONTEXT.set::<CasbinService>(CasbinService::default().await);
}
初始化的时候是直接放到 全局的单例池里的
为什么要这么做呢 权限资源在项目启动的时候
首次加载到缓存里,后续管理端操作用户权限信息的
时候要同步到缓存里 所以要从单例池里能拿到才行