Casbin权限模型
权限框架casbin
1.概述
Casbin是一个强大的、高效的开源访问控制框架,其权限管理机制支持多种访问控制模型。
Casbin支持以下编程语言:
Casbin可以做到:
支持自定义请求的格式,默认的请求格式为{subject, object, action}。
具有访问控制模型model和策略policy两个核心概念。
支持RBAC中的多层角色继承,不止主体可以有角色,资源也可以具有角色。
支持超级用户,如 root 或 Administrator,超级用户可以不受授权策略的约束访问任意资源。
支持多种内置的操作符,如 keyMatch,方便对路径式的资源进行管理,如 /foo/bar 可以映射到 /foo*
Casbin不能做到:
身份认证 authentication(即验证用户的用户名、密码),casbin只负责访问控制。应该有其他专门的组件负责身份认证,然后由casbin进行访问控制,二者是相互配合的关系。
管理用户列表或角色列表。 Casbin 认为由项目自身来管理用户、角色列表更为合适, 用户通常有他们的密码,但是 Casbin 的设计思想并不是把它作为一个存储密码的容器。 而是存储RBAC方案中用户和角色之间的映射关系
github:https://github.com/casbin/casbin
docs:https://casbin.org/docs/zh-CN/overview
2.工作原理
在 Casbin 中, 访问控制模型被抽象为基于 PERM (Policy, Effect, Request, Matcher) 的一个文件。 因此,切换或升级项目的授权机制与修改配置一样简单。
PERM模型
PERM(Policy, Effect, Request, Matchers)模型很简单, 但是反映了权限的本质 – 访问控制
Policy: 定义权限的规则
Effect: 定义组合了多个 Policy 之后的结果, allow/deny
Request: 访问请求, 也就是谁想操作什么
Matcher: 判断 Request 是否满足 Policy
[外链图片转存失败(img-ys2XIpxc-1565944147357)(C:\Users\Todd\AppData\Roaming\Typora\typora-user-images\1565593950617.png)]
Module File 语法
casbin 是基于 PERM 的, 所有 model file 中主要就是定义 PERM 4 个部分
1.Request definition
[request_definition]
r = sub, obj, act
分别表示 request 中的
accessing entity (Subject)
accessed resource (Object)
the access method (Action)
2.Policy definition
[policy_definition]
p = sub, obj, act
p2 = sub, act
定义的每一行称为 policy rule, p, p2 是 policy rule 的名字. p2 定义的是 sub 所有的资源都能执行 act
3.Policy effect
[policy_effect]
e = some(where (p.eft == allow))
上面表示有任意一条 policy rule 满足, 则最终结果为 allow
4.Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
定义了 request 和 policy 匹配的方式, p.eft 是 allow 还是 deny, 就是基于此来决定的
5.Role
[role_definition]
g = _, _
g2 = _, _
g3 = _, _, _
g, g2, g3 表示不同的 RBAC 体系, _, _ 表示用户和角色 _, _, _ 表示用户, 角色, 域
您可以通过组合可用的模型来定制您自己的访问控制模型。 例如,您可以在一个model中获得RBAC角色和ABAC属性,并共享一组policy规则。
Casbin中最基本、最简单的model是ACL。ACL中的model CONF为:
# Request definition
[request_definition]
r = sub, obj, act # Policy definition
[policy_definition]
p = sub, obj, act # Policy effect
[policy_effect]
e = some(where (p.eft == allow)) # Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
ACL model的示例policy如下:
p, alice, data1, read
p, bob, data2, write
这表示:
alice可以读取data1
bob可以编写data2
Model存储
从 .CONF 文件中加载 model
e := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
从代码加载 model
// Initialize the model from Go code.
m := casbin.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("g", "g", "_, _")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act") // Load the policy rules from the .CSV file adapter.
// 使用自己的 adapter 替换。
a := persist.NewFileAdapter("examples/rbac_policy.csv") // 创建一个 enforcer。
e := casbin.NewEnforcer(m, a)
从字符串加载的 model(推荐)
// Initialize the model from a string.
text :=
`
[request_definition]
r = sub, obj, act [policy_definition]
p = sub, obj, act [role_definition]
g = _, _ [policy_effect]
e = some(where (p.eft == allow)) [matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
`
m := NewModel(text) // Load the policy rules from the .CSV file adapter.
// Replace it with your adapter to avoid files.
a := persist.NewFileAdapter("examples/rbac_policy.csv") // Create the enforcer.
e := casbin.NewEnforcer(m, a)
这种方法的优点是您不需要维护模型文件
Casbin API
//全局变量 e是执行者实例
e := NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv") //获取当前策略中显示的主题列表
allSubjects := e.GetAllSubjects() //获取当前命名策略中显示的主题列表
allNamedSubjects := e.GetAllNamedSubjects("p") //获取当前策略中显示的对象列表
allObjects := e.GetAllObjects() //获取当前命名策略中显示的对象列表
allNamedObjects := e.GetAllNamedObjects("p") //获取当前策略中显示的操作列表
allActions := e.GetAllActions() //获取当前命名策略中显示的操作列表
allNamedActions := e.GetAllNamedActions("p") //获取当前策略中显示的角色列表
allRoles = e.GetAllRoles() //获取当前命名策略中显示的角色列表
allNamedRoles := e.GetAllNamedRoles("g") //获取策略中的所有授权规则
policy = e.GetPolicy() //获取策略中的所有授权规则,可以指定字段筛选器
filteredPolicy := e.GetFilteredPolicy(0, "alice") //获取命名策略中的所有授权规则
namedPolicy := e.GetNamedPolicy("p") //获取命名策略中的所有授权规则,可以指定字段过滤器
filteredNamedPolicy = e.GetFilteredNamedPolicy("p", 0, "bob") //获取策略中的所有角色继承规则
groupingPolicy := e.GetGroupingPolicy() //获取策略中的所有角色继承规则,可以指定字段筛选器
filteredGroupingPolicy := e.GetFilteredGroupingPolicy(0, "alice") //获取策略中的所有角色继承规则
namedGroupingPolicy := e.GetNamedGroupingPolicy("g") //获取策略中的所有角色继承规则
namedGroupingPolicy := e.GetFilteredNamedGroupingPolicy("g", 0, "alice") // 确定是否存在授权规则
hasPolicy := e.HasPolicy("data2_admin", "data2", "read") //确定是否存在命名授权规则
hasNamedPolicy := e.HasNamedPolicy("p", "data2_admin", "data2", "read") //向当前策略添加授权规则。 如果规则已经存在,函数返回false,并且不会添加规则。 否则,函数通过添加新规则并返回true
added := e.AddPolicy("eve", "data3", "read") // 向当前命名策略添加授权规则。 如果规则已经存在,函数返回false,并且不会添加规则。 否则,函数通过添加新规则并返回true
added := e.AddNamedPolicy("p", "eve", "data3", "read") // 从当前策略中删除授权规则
removed := e.RemovePolicy("alice", "data1", "read") // 移除当前策略中的授权规则,可以指定字段筛选器。 RemovePolicy 从当前策略中删除授权规则
removed := e.RemoveFilteredPolicy(0, "alice", "data1", "read") //从当前命名策略中删除授权规则
removed := e.RemoveNamedPolicy("p", "alice", "data1", "read") //从当前命名策略中移除授权规则,可以指定字段筛选器
removed := e.RemoveFilteredNamedPolicy("p", 0, "alice", "data1", "read") //确定是否存在角色继承规则
has := e.HasGroupingPolicy("alice", "data2_admin") //确定是否存在命名角色继承规则
has := e.HasNamedGroupingPolicy("g", "alice", "data2_admin") // 向当前策略添加角色继承规则。 如果规则已经存在,函数返回false,并且不会添加规则。 如果规则已经存在,函数返回false,并且不会添加规则
added := e.AddGroupingPolicy("group1", "data2_admin") //将命名角色继承规则添加到当前策略。 如果规则已经存在,函数返回false,并且不会添加规则。 否则,函数通过添加新规则并返回true
added := e.AddNamedGroupingPolicy("g", "group1", "data2_admin") // 从当前策略中删除角色继承规则
removed := e.RemoveGroupingPolicy("alice", "data2_admin") //从当前策略中移除角色继承规则,可以指定字段筛选器
removed := e.RemoveFilteredGroupingPolicy(0, "alice") //从当前命名策略中移除角色继承规则
removed := e.RemoveNamedGroupingPolicy("g", "alice") //当前命名策略中移除角色继承规则,可以指定字段筛选器
removed := e.RemoveFilteredNamedGroupingPolicy("g", 0, "alice") //添加自定义函数
func CustomFunction(key1 string, key2 string) bool {
if key1 == "/alice_data2/myid/using/res_id" && key2 == "/alice_data/:resource" {
return true
} else if key1 == "/alice_data2/myid/using/res_id" && key2 == "/alice_data2/:id/using/:resId" {
return true
} else {
return false
}
} func CustomFunctionWrapper(args ...interface{}) (interface{}, error) {
key1 := args[].(string)
key2 := args[].(string) return bool(CustomFunction(key1, key2)), nil
} e.AddFunction("keyMatchCustom", CustomFunctionWrapper)
casbin的使用者
casbin-go语言使用者
名称 描述 模型 策略
VMware Harbor VMware的开源可信云本地注册表项目,用于存储、签名和扫描内容。 Code Code
Intel RMD 英特尔的资源管理守护进程。 .conf .csv
VMware Dispatch 用于部署和管理无服务器风格应用程序的框架。 Code Code
Skydive 一个开源的实时网络拓扑和协议分析器。 Code .csv
Zenpress 用Golang编写的CMS系统。 .conf Gorm
Argo CD 为Kubernetes持续提供的GitOps。 .conf .csv
Muxi Cloud 一种更容易管理Kubernetes集群的方法。 .conf Code
EngineerCMS CMS管理工程师的知识。 .conf SQLite
Cyber Auth API 一个Golang身份验证API项目 .conf .csv
IRIS Community IRIS社区活动网页 .conf .csv
Metadata DB BB归档元数据数据库。 .conf .csv
Qilin API 游戏内容下的ProtocolONE许可证管理工具。 Code .csv
3.权限系统设计模型分析
常见的设计模式(DAC,MAC,RBAC,ABAC)
自主访问控制(DAC: Discretionary Access Control)
系统会识别用户,然后根据被操作对象(Subject)的权限控制列表(ACL: Access Control List)或者权限控制矩阵(ACL: Access Control Matrix)的信息来决定用户的是否能对其进行哪些操作,例如读取或修改。
而拥有对象权限的用户,又可以将该对象的权限分配给其他用户,所以称之为“自主(Discretionary)”控制。
这种设计最常见的应用就是文件系统的权限设计,如微软的NTFS。
DAC最大缺陷就是对权限控制比较分散,不便于管理,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户
强制访问控制(MAC: Mandatory Access Control)
MAC是为了弥补DAC权限控制过于分散的问题而诞生的。在MAC的设计中,每一个对象都都有一些权限标识,每个用户同样也会有一些权限标识,而用户能否对该对象进行操作取决于双方的权限标识的关系,这个限制判断通常是由系统硬性限制的。比如在影视作品中我们经常能看到特工在查询机密文件时,屏幕提示需要“无法访问,需要一级安全许可”,这个例子中,文件上就有“一级安全许可”的权限标识,而用户并不具有。
MAC非常适合机密机构或者其他等级观念强烈的行业,但对于类似商业服务系统,则因为不够灵活而不能适用。
基于角色的访问控制(RBAC: Role-Based Access Control)
因为DAC和MAC的诸多限制,于是诞生了RBAC,并且成为了迄今为止最为普及的权限设计模型。
RBAC在用户和权限之间引入了“角色(Role)”的概念(暂时忽略Session这个概念):
如图所示,每个用户关联一个或多个角色,每个角色关联一个或多个权限,从而可以实现了非常灵活的权限管理。角色可以根据实际业务需求灵活创建,这样就省去了每新增一个用户就要关联一遍所有权限的麻烦。简单来说RBAC就是:用户关联角色,角色关联权限。另外,RBAC是可以模拟出DAC和MAC的效果的。
基于属性的权限验证(ABAC: Attribute-Based Access Control)
ABAC被一些人称为是权限系统设计的未来。
不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)和对象属性(如一篇文章,又称资源属性),所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。
例如规则:“允许所有班主任在上课时间自由进出校门”这条规则,其中,“班主任”是用户的角色属性,“上课时间”是环境属性,“进出”是操作属性,而“校门”就是对象属性了。为了实现便捷的规则设置和规则判断执行,ABAC通常有配置文件(XML、YAML等)或DSL配合规则解析引擎使用。
用户在携带自身的属性值包括主题属性,资源属性,环境属性,然后向资源发送请求,授权引擎 会根据subject所携带的属性进行判断,然后会给出拒绝或者同意的结果给用户,然后就可以访问资源。
总结一下,ABAC有如下特点:
集中化管理
可以按需实现不同颗粒度的权限控制
不需要预定义判断逻辑,减轻了权限系统的维护成本,特别是在需求经常变化的系统中
定义权限时,不能直观看出用户和对象间的关系
规则如果稍微复杂一点,或者设计混乱,会给管理者维护和追查带来麻烦
权限判断需要实时执行,规则过多会导致性能问题
既然ABAC这么好,那最流行的为什么还是RBAC呢?
大部分系统对权限控制并没有过多的需求,而且ABAC的管理相对来说太复杂了。
ABAC有时也被称为PBAC(Policy-Based Access Control)或CBAC(Claims-Based Access Control)
4.百度超级链权限系统
wiki地址:https://github.com/xuperchain/xuperunion/wiki/2.-关键概念#26-账户权限控制模型
名词解释
AK(Access Key):具体的一个address,由密码学算法生成一组公私钥对,然后将公钥用指定编码方式压缩为一个地址。
账号(Account): 在超级链上部署合约需要有账号, 账号可以绑定一组AK(公钥),并且AK可以有不同的权重。 账户的名字具有唯一性。
模型介绍
系统会首先识别用户,然后根据被操作对象的ACL的信息来决定用户能否对其进行哪些操作
ACL(Access Control List)是最早也是最基本的一种访问控制机制,它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD中的那些操作。当系统试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。总得来说,ACL是一种面向资源的访问控制模型,它的机制是围绕“资源”展开的
在超级链中,账户和合约的关系如下所述:
个人账户AK:是指一个具体的地址Addr;
用户的创建是离线的行为,可以通过命令行工具或者API进行创建
合约账户:超级链智能合约的管理单元。
账户的创建:
任何账户或者AK都可以调用系统级智能合约创建账户;
创建账户需要指定账户对应的拥有者的地址集,如果一个账户中只有一个地址, 那么这个Addr对账户完全控制;
创建账户需要指定ACL控制策略,用于账户其他管理动作的权限控制;
创建账户需要消耗账户资源;
账户名命名规则;
中间为长度为16位字符串;
以"XC"开头;
以"@链名"结尾;
账户管理:依地址集合据创建时指定的地址集和权限策略,管理账户其他操作;
账户股东剔除和加入;
账户资产转账;
创建合约,创建智能合约需要消耗账户资源,先将utxo资源打到账户下,通过消耗账户的utxo资源创建合约,验证的逻辑需要走账户的ACL控制;
合约Method权限模型管理;
智能合约:超级链中的一个具体的合约,属于某个账户;
账户所属人员允许在账户内部署合约;
账户所属人员可以定义合约管理的权限模型;
设置合约方法的权限模型,合约内有一个权限表,记录:{ contract.method,permission_model}
合约命名规则:长度为4~16个字符(包括4和16),首字母可选项为[ a-ZA-Z_ ],末尾字符可选项为[ a-zA-Z0-9_ ],中间部分的字符可选项为[ a-zA-Z_. ]
account := "XC0000000000000001@xuper"
ak := "XC0000000000000001@xuper/dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN"
系统功能和设计
主要有两个功能:账号权限管理、合约权限管理
账号权限管理 账号的创建、添加和删除AK、设置AK权重、权限模型
合约权限管理 设置合约调用权限, 支持2种权限模型: a. 背书阈值:在名单中的AK或Account签名且他们的权重值加起来超过一定阈值,就可以调用合约 b. AK集合: 定义多组AK集合,集合内的AK需要全部签名,集合间只要有一个集合有全部签名即可
系统设计
权限策略:
var PermissionRule_name = map[int32]string{
0: "NULL", // 无权限控制
1: "SIGN_THRESHOLD",// 签名阈值策略
2: "SIGN_AKSET", // AKSet签名策略
3: "SIGN_RATE", // 签名率策略
4: "SIGN_SUM", // 签名个数策略
5: "CA_SERVER", // CA服务器鉴权
6: "COMMUNITY_VOTE",// 社区治理
}
//签名阈值策略:
Sum{Weight(AK_i) , if sign_ok(AK_i)} >= acceptValue
权限测试例:
func Test_IdentifyAccount(t *testing.T) {
account := "XC0000000000000001@xuper"
ak := "XC0000000000000001@xuper/dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN"
pubkey := "{\"Curvname\":\"P-256\",\"X\":74695617477160058757747208220371236837474210247114418775262229497812962582435,\"Y\":51348715319124770392993866417088542497927816017012182211244120852620959209571}"
prikey := "{\"Curvname\":\"P-256\",\"X\":74695617477160058757747208220371236837474210247114418775262229497812962582435,\"Y\":51348715319124770392993866417088542497927816017012182211244120852620959209571,\"D\":29079635126530934056640915735344231956621504557963207107451663058887647996601}"
msg := "this is the test message from permission" xcc, err := crypto_client.CreateCryptoClientFromJSONPublicKey([]byte(pubkey))
if err != nil {
t.Error("create crypto client failed, err=", err)
return
} ecdsaPriKey, err := xcc.GetEcdsaPrivateKeyFromJSON([]byte(prikey))
if err != nil {
t.Error("get private key failed, err=", err)
return
} sign, err := xcc.SignECDSA(ecdsaPriKey, []byte(msg))
if err != nil {
t.Error("sign failed, err=", err)
return
} signInfo := &pb.SignatureInfo{
Sign: sign,
PublicKey: pubkey,
} aks := make([]string, 1)
signs := make([]*pb.SignatureInfo, 1) aks[] = ak
signs[] = signInfo
aclMgr, err := acl_mock.NewFakeACLManager()
if err != nil {
t.Error("NewAclManager failed, err=", err)
return
}
pm := &pb.PermissionModel{
Rule: pb.PermissionRule_SIGN_THRESHOLD,
AcceptValue: 1,
}
aclObj := &pb.Acl{
Pm: pm,
AksWeight: make(map[string]float64),
} aclObj.AksWeight["dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN"] = 1
aclMgr.SetAccountACL(account, aclObj)
//主要为了实现IdentifyAccount方法
//SetAccountAC/ IdentifyAccount检查aks和符号是否匹配,这些aks可以通过account的ACL策略表示 给定的帐户。如果签名匹配aks,并且aks可以代表帐户,则返回true。将账户acl保存在内存中
result, err := IdentifyAccount(account, aks, signs, []byte(msg), aclMgr)
if err != nil || !result {
t.Error("IdentifyAccount failed, err=", err)
return
} fakesign := "this is a fake signature"
signInfo2 := &pb.SignatureInfo{
Sign: []byte(fakesign),
PublicKey: pubkey,
} signs[] = signInfo2
result, err = IdentifyAccount(account, aks, signs, []byte(msg), aclMgr)
if result == true {
t.Error("IdentifyAccount fake sign failed, result=", result)
}
}
在IdentifyAccount方法中主要实现:
func IdentifyAccount(account string, aksuri []string, signs []*pb.SignatureInfo,
msg []byte, aclMgr acl.ManagerInterface) (bool, error) {
akslen := len(aksuri)
signslen := len(signs)
// aks and signs could have zero length for permission rule Null
if akslen != signslen || aclMgr == nil {
return false, fmt.Errorf("Invalid Param, akslen=%d,signslen=%d,aclMgr=%v", akslen, signslen, aclMgr)
} // build perm tree
pnode, err := ptree.BuildAccountPermTree(aclMgr, account, aksuri, signs)
if err != nil {
return false, err
} return validatePermTree(pnode, msg, true)
}
在这其中主要实现buildAccountPermTree和validatePermTree两个方法,Pnode定义了perm 树的节点
type PermNode struct {
Name string // the name(id) of account/ak/method
ACL *pb.Acl // the ACL definition of this account/method
Status ValidateStatus // the ACL validation status of this node
SignInfo *pb.SignatureInfo // the signature info of this node, only AK have this field
Children []*PermNode // the children of this node, usually are ACL members of account/method
} const (
_ ValidateStatus = iota
// NotVerified : not verified by ACLValidator
NotVerified
// Success : ACLValidator verified successful
Success
// Failed : ACLValidator verified failed
Failed
)
它也没有使用PERM模型,至于为什么会用Perm这个词,目前也没想明白。
5.ABAC 模型示例
package main import (
"fmt"
"github.com/casbin/casbin"
"github.com/casbin/casbin/model"
)
const modelText = `
[request_definition]
r = sub, obj, act [policy_definition]
p = sub, obj,act [policy_effect]
e = some(where (p.eft == allow)) [matchers]
m = r.sub.App == r.obj.App && r.sub.Type == r.obj.Type && r.sub.Method == r.obj.Method && r.sub.Name == r.obj.Name \
&& r.sub.Read == r.act.Read && r.sub.Write == r.act.Write
` type User struct {
Id int
UserName string
Group []Group
}
type Group struct {
Id int
Name string
Read bool
Write bool
App string // app
Type string // 类型
Method string // 方法
Priority int // 优先级
} type Obj struct {
App string // app
Name string
Type string // 类型
Method string // 方法
} type Act struct {
Read bool
Write bool
} func main() {
m := model.Model{}
m.LoadModelFromText(modelText)
e:= casbin.NewEnforcer(m)
group1 := Group{
Name: "lk",
Read: true,
Write: true,
App: "asset",
Type: "user",
Method: "Get",
Priority: 100,
}
//group2 中Name和Write 不与Obj资源和执行操作权限中相同
group2 := Group{
Name: "lkTest",
Read: true,
Write: false,
App: "asset",
Type: "user",
Method: "Get",
Priority: 100,
} // 用户 palletone 属于 group1 , group2
user1 := User{
UserName: "palletone",
Group: []Group{group1, group2},
}
//资源属性
obj := Obj{
App: "asset",
Name: "lk",
Type: "user",
Method: "Get",
}
//当执行操作权限 Read Write为True时 策略执行结果为allow
act := Act{
Read:true,
Write:true,
}
// 检查 用户 palletone 所有的组 是否有权限
for _, v := range user1.Group {
//强制决定一个“subject”是否可以通过操作“action”访问一个“object”,输入参数通常是:(sub, obj, act)。
flag:= e.Enforce(v, obj, act)
if flag {
fmt.Println("权限正常")
} else {
fmt.Println("没有权限")
}
} } //打印结果 //权限正常
//没有权限
————————————————
版权声明:本文为CSDN博主「lk2684753」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lk2684753/article/details/99680892
Casbin权限模型的更多相关文章
- YbSoftwareFactory 代码生成插件【十七】:先进的权限模型体系设计
目前权限管理系统不少,但通用.灵活.符合现代企事业单位实际工作需要的不多.现有的权限系统绝大多数都是以模块为核心,而本权限模型将摒弃此类普遍的做法,将以组织机构为核心来进行权限系统的设计,因为这更符合 ...
- Project Server 2013两个权限模型介绍
Project Server 2013中无法使用“新建用户”功能? 当我们的Project Server 2013刚刚安装好时,在PWA的服务器设置中找不到新建用户的选项,是什么原因造成的呢? 原来是 ...
- RBAC权限模型——项目实战(转)
一.前言 权限一句话来理解就是对资源的控制,对web应用来说就是对url的控制,关于权限可以毫不客气的说几乎每个系统都会包含,只不过不同系统关于权限的应用复杂程序不一样而已,现在我们在用的权限模型基本 ...
- (转)RBAC权限模型——项目实战
一.前言 权限一句话来理解就是对资源的控制,对web应用来说就是对url的控制,关于权限可以毫不客气的说几乎每个系统都会包含,只不过不同系统关于权限的应用复杂程序不一样而已,现在我们在用的权限模型基本 ...
- 权限模型AGDLP
关于权限模型,认真学习下AD+FS应用在企业中,使用AGDLP模型,即可. AD是微软最牛逼的设计之一.
- RBAC 几种常见的控制权限模型
1. 几种常见的权限模型 2. ACL 和 RBAC 对比 3. RBAC 权限模型的优势 (1)简化了用户和权限的关系 (2).易于扩展 易于维护 4.优势(给权限和收回权限) 5.架构
- 权限管理系统(四):RBAC权限模型分类介绍
RBAC是Role-BasedAccess Control的英文缩写,意思是基于角色的访问控制.RBAC认为权限授权实际上是Who.What.How的问题.在RBAC模型中,who.what.how构 ...
- RBAC权限模型及数据权限扩展的实践
话说大家对RBAC权限模型应该是耳熟能详了.但真正用的好的并不多.并且原始的RBAC模型并不包括数据权限的管理,网上也差点儿没有相关的文章可以參考.本人经过几个项目的实战,在其基础上扩展出一套可行的. ...
- RBAC权限模型——项目实战
RBAC权限模型——项目实战
随机推荐
- python asyncio 使用ThreadPoolExecutor和asyncio完成阻塞IO请求
#使用多线程:在协程中集成阻塞io import asyncio from concurrent.futures import ThreadPoolExecutor import socket fro ...
- win10怎么打开服务界面?
在键盘上同时点击“win+R”键弹出运行界面,输入services.msc,按确定. 这时就弹出了服务的界面,如图:
- Java基础扫盲系列(三)— Java内省技术
前言 Java内省技术属于Java基础体系的的一部分,但是很多人都不甚了解.笔者也是在学习Spring源码的过程中遇到该技术模块的.为了完善技术体系,本文将全面的学习该技术.在提到Java内省技术,就 ...
- Python-绘制3D柱形图
Python-绘制3D柱形图 本文主要讲解如何使用python绘制三维的柱形图,可以得到图1所示的效果. 图1 源代码如下: import numpy as np import matplotlib. ...
- js变量类型及检查
一.变量的类型 JavaScript 有六种数据类型.主要的类型有 Number.String.object 以及 Boolean 类型,其他两种类型为 null 和 undefined.var ob ...
- Delphi - 操作Excel数据公式的实现
procedure TF_SMP_FT_NEW.RzBitBtn_StartToChangeClick(Sender: TObject); var i, j, ni, nj, iRows, iCol, ...
- Unable to connect to web server 'IIS Express'(无法连接到Web服务器“IIS Express”)的解决方式-Jexus Manager
在运行微软示例工程eShopOnWeb时候, 在经过一段时间再运行启动报Error "Unable to connect to web server 'IIS Express'" ...
- 高精度gcd
#include<iostream> #include<cstdio> #include<cstring> #define inf 1000000000 using ...
- Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)
Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...
- centos下非yum方式安装docker环境
1.下载docker源码包 docker官网地址: https://download.docker.com/linux/static/stable/ 选择.tgz的包下载,例如:https://dow ...