五一假期疫情封在家也没事做,就想来优化一下一个前端容器小项目
之前的TODOlist里面有一项是权限这块时隔2年了还一直没有动手
迟迟没搞主要还是我太懒了,哈哈 其实我一直想要找一个轻量级的权限通用方案
知道我最近研究了一下casbin(基于各种访问控制模型的授权), 发现它正好满足了我以上几个点 官网: https://casbin.org/
分为2种权限:超级管理员(上帝模式) 和 普通用户
我这个程序的功能是按照项目维度来区分的,超级管理员创建一个空项目后,授权给别人去维护,总共包含7大功能:
超级管理员可以访问所有功能, 但只能是【超级管理员】做的有1和2和3
普通用户则可以被超级管理员在权限配置页面创建并进行配置来限制是否授予访问4~7这几个功能
casbin基本主流的开发语言都有对应的实现,这里我用netcore版本(Casbin.NET)
首先定义模型:
[request_definition] r = sub, obj, act [policy_definition] p = sub, obj, act [policy_effect] e = some(where (p.eft == allow)) [matchers] r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act) || r.sub == "root"
由于我这个是按照project进行权限控制的,所以我选用的是这个模型
/// <summary> /// 创建casbin模型 /// </summary> /// <returns></returns> public static Enforcer createEnforcer() { var e = new Enforcer(); var m = NetCasbin.Model.Model.CreateDefault(); m.AddDef("r", "r", "sub, obj, act"); m.AddDef("p", "p", "sub, obj, act"); m.AddDef("e", "e", "some(where (p.eft == allow))"); m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act) || r.sub == "root""); var csv = Path.Combine(WebRootPath, CasBinPolicyFile); if (!File.Exists(csv)) { File.CreateText(csv); } e.SetModel(m); // 目前我的权限配置文件是放在csv文件中 切换成存db的话 就切换一个adapter e.SetAdapter(new DefaultFileAdapter(csv)); e.LoadPolicy(); return e; }
由于本身我的这个项目是一个中间件,
//内部api app.UseWhen( c => { // 检查路由是否满足要求 if (!ApiMiddleware.CanInvoke(c, out var route)) { return false; } // 路由规则满足后检查api是否存在 return c.RequestServices.GetService<SpaDomain>()?.IsSpaApi(route.Item2) ?? false; }, _ => _.UseMiddleware<ApiMiddleware>());
对于普通用户可访问的内部的api访问路径进行规则约束
这样我在ApiMiddleware里面可以进行统一权限拦截处理了
bool isAuthed = ef.Enforce(sub, obj, act);
这也是针对casbin的一个ui操作的封装
那么通过这个ui操作就很容易去配置
如上图,资源路径我配置了/* 代表这个zdyu用户可以访问project:test的所有操作
如上图,代表zdyu这个用户只荀彧访问test这个project下的 部署和回滚2个功能
本身研究怎么用casbin是非常简单的,这里主要分享了结合具体项目来如何设计,细节源码可以查看
spa单页面容器里面一个project相当于一个二级域名的应用,应用内互相隔离,可以代替部署nginx或apache,对前端开发者友好,适合在某些只是用来静态项目访问的场景,来提高效率!