本文主要介绍了 Salesforce 对于系统中数据的访问控制是如何设计的, 然后也了解了下 Alfresco 和 Oracle VPD 的数据权限机制. 希望对一些业务系统的数据权限的访问控制设计能有所参考和启发.
Salesforce
1. 产品功能
salesforce 是基于 SaaS 的客户关系管理系统(CRM), 该系统提供的功能覆盖了众多不同的业务领域, 例如: 客户资料存储, 销售业务管理, 协同办公等. 在此基础上, Salesforce 又提供了一个开发平台以帮助其客户根据自身的需求对核心系统进行定制和扩展.
2. 数据权限配置
在 salesforce 平台, 可以控制哪些用户可以访问哪些 Organization, Objects, Fields, Records 的数据, 通过结合不同级别的安全控制, 来为成千上万的应用提供恰到好处的数据访问级别.
例如下面是在 salesforce 平台上的一个招聘系统, 开发者配置的数据权限:
如上图中:
Objects-Level Security: 对象级别的数据权限, 类似 DB 中的表. 例如: 面试官只能查看候选人和招聘职位信息, 而不能查看 offer 信息.
Field-Level Security: 列数据权限, 类似 DB 表的列字段. 例如: 面试官可以查看候选人的姓名, 住址, 而不能查看电话号码, 薪资等敏感信息.
Record-Level Security: 行数据权限, 类似 DB 表中的行记录. 例如: 面试官只能查看自己所在部门下的候选人信息, 而不能查看其它部门下的候选人信息.
下面详细描述 salesforce 中数据的 4 种安全级别控制:
1)Organization 的数据访问控制
只有通过认证的员工才能登录到系统, 是最广泛的数据保护级别. 常用的设定有用户管理, 密码登录, 登录 IP 限制等.
2)Objects 的数据访问控制
Object 可以看做表. Object 是由 Records 组成, 通过 profile 和 permission sets 来设置 objects 的数据访问权限. 一个用户会有一个 profile 和许多 permission sets.
profile(简档): 是 salesforce 为每个用户指定的标准配置文件, 在创建用户时候指定(不同用户可使用同一 profile). 通过一组规则集合, 规定了用户对这个系统各方面的权限. 分为 settings 和 permissions 两部分:
settings: 决定用户可以访问哪些 objects
permissions: 对 objects 上的 records 能执行哪些操作: 增删改查
permission sets(权限集): 分配给用户额外的权限和访问规则, 也由 settings 和 permissions 组成. permission sets 的权限范围和 profile 是类似的.
一个用户只能有一个 profile, 但可以有多个 permission sets. 一般使用 profile 分配给用户最低的权限集合, 然后使用 permission sets 补充配置的其他权限. 两个联合使用, 提供了访问 objects 的灵活性.
下图是 profile 中对象的权限设定:
3)Fields 的列访问控制
Field 可看做表中的列. 有时, 用户可以访问 Objects, 但不能访问 / 修改 Object 的 Fields, 例如: 身份证信息, 薪资信息等. Fields 列权限可通过 profile,permission sets 来控制
4)Records 的行访问控制
Record 可看做表中的行记录. 用户访问 Objects 时只能访问子集中的一部分 Records. 而控制 Records 的数据访问范围有四个方法:
Org-wide defaults: 组织范围内的默认基础设置. 共享设置是数据安全级别的最底层, 如果用户在 profiles 或其他地方对某些对象有其他权限设定, 则此处的权限设定会被忽略.
可以对系统中每个对象进行访问权限设置, 例如下图:
有以下四种策略:
Private: 只有 record 的拥有者(owner), 以及上级能查看, 编辑
Public Read Only: 所有用户可查看 records, 但只有拥有者和上级能编辑
Public Read/Write: 所有用户可以查看, 编辑 records
Controlled by Parent: 一个用户可查看, 编辑, 删除一个 record, 那就可对该 record 下面的 record 做同样操作.
Role hierarchies:salesforce 的角色是层级结构, 类似于一个树, 拥有上级角色可以同时拥有这个角色树节点下级的所有角色的 Record 权限.
Sharing rules: 将符合规则的一些行数据, 赋予符合规则的一些用户. 一条共享规则包括:
基本属性: 标签, 名字, 描述等
规则类型: 可以设定基于记录所有人, 还是基于某些条件
被共享的用户: 可以设定此共享规则对哪些用户生效. 此处的用户分为三种: 公用小组, 角色, 角色及下属
被共享用户的访问权限: 被共享的用户对于此数据有哪些权限
例如下图:
Manual sharing: 手动共享一条记录给其他人. Records 的拥有者给没有 Records 权限的用户授予该 Record 相应的读写权限.
3. 数据权限校验
当用户需要进入某条记录, 运行报表, 搜索等操作时, salesforce 会检查用户的权限. 由于 salesforce 有着复杂的权限设定, 会在权限设定更改时立即计算数据记录的权限, 然后将结果保存起来. 这样, 当用户对记录操作时, 不用在此时进行权限的计算(因为会使效率变慢), 而是根据存储好的权限结果直接判断.
salesforce 主要使用三种数据表来管理各种权限设定:
对象记录表(Object Record Table): 存储着数据记录
对象共享表(Object Sharing Table): 存储着各个对象的共享权限, 包括了各种权限设定: Role hierarchies, Sharing rules, Manual sharing 等
用户组表(Group Maintenance Table): 存储着各个用户和用户组的关系
当需要决定某个用户或用户组对于某条记录的权限时, 会执行以下步骤:
在对象记录表中找到这条记录
在对象共享表中根据这条记录的 ID 找到存储于其中的共享权限
在用户组表中根据用户或组的 ID 找到对应的记录, 然后在对象共享表中找到和该用户或组的 ID 相对应的共享权限
以上步骤执行完毕后, salesforce 便得到了该用户或用户组对于这条记录的权限.
4. 数据定义与存储
Metadatas 表: 存储用户自定义的对象 (Record) 和对象所包含的字段 (Field) 的结构信息, 不保存具体的数据. Metadata 可以保证极大的灵活性, 搭配着配置化平台使用. 主要有两大类:
Objects Metadata 表: 存储对象的信息, 主要字段包括: 对象 ID(ObjID), 拥有这个对象的租户 ID(OrgID), 对象的名称 (ObjName) 等
Fields Metadata 表: 存储对象附带字段的信息, 主要字段包括: 字段 ID(FieldID), 拥有这个字段的租户 ID(OrgID), 对象 ID(ObjID), 字段的名称(FieldName), 字段的数据类型(DataType), 布尔字段表示这个字段是否需要被检索(IsIndexed)
Data 表: 存储用户定制的对象和对象所包含字段的数据. 主要也是两大类:
Data 表: 存储 Metadata 表中定义的对象和字段所对应的数据, 主要字段包括: 全局唯一 ID(GUID), 租户 ID(OrgID), 对象 ID(ObjID), 存放对象名字的 Nature Name(例如: 这行与会计对象有关, 这行的 Nature Name 就可能是 "Account Name"). 除了这些核心字段外, 这个表还有名字从 Value0~Value500 这 501 个列来存储数据, 而且这些列都是 varchar 格式来存储不同类型的数据, 这个列也成为 flex 列.
Clob 表: 存储那些 CLOD(Character Large Object, 字符大对象)数据, 对象最大支持 32000 个字符.
Piovt 表: 也称 "数据透视表", 以去规范化格式存储那些用于特殊目的的数据, 比如用于检索, 唯一性和关系等. 主要作用是提升处理这些特殊数据的读取性能. 主要有五种 Piovt 表:
Index Piovt 表: 由于 Data 表中数据都是以 flex 列的形式存储, 所有很难在 Data 表的基础上对数据进行检索, 所以引入 Index Piovt 表来解决这个问题, 系统运行时, 将需要索引的数据从 Data 表同步至 Index Piovt 表中相对应的字段来方便检索. 比如数据的类型是日期型的, 那么它会被同步至 Index Piovt 表中的日期字段.
UniqueFields Piovt 表: 用于帮助系统在 Data 表中字段实现唯一性约束
Relationships Piovt 表: 提供了 "Relationship" 这个数据类型来支持定义多个对象之间的关系, 此表方便和加速了 "Relationship" 数据读取的作用
NameDenorm 表: 是一个简单的数据表用于存储对象的 ID(ObjID)和对象的实例的名字, 主要让一些仅需获取名字的查询访问, 让一些简单的查询无需访问规模庞大的 Data 表
FallbackIndex 表: 这个表记录所有对象的名字, 免去成本高昂的 "UNION" 操作, 从而加速查询
对于 Data,Objects 和 Fields 表的举例如下:
Objects Metadata 表: 定义正常数据库设计的 user 表和 order 表
ObjID | OrgID | ObjName | ... |
001 | 10 | user | ... |
002 | 10 | order | ... |
Fields Metadata 表: 定义 user 表和 order 表的字段, user(userId, name, age),order(orderId, amount)
FieldID | OrgID | ObjID | FieldName | DataType | IsIndexed | FieldNum | ... |
001 | 10 | 001 | userId | string | true | 0 | ... |
002 | 10 | 001 | name | string | true | 1 | ... |
003 | 10 | 001 | age | int | false | 2 | ... |
004 | 10 | 002 | amount | long | false | 1 | ... |
005 | 10 | 002 | orderId | string | true | 0 | ... |
Data 表: user 表和 order 表的具体内容. Value0, Value1 等值的顺序与 Fields 中 FileldNum 相对应, user.userId 的 FileldNum=0, 则 Value0 存储着 userId 的具体值
GUID | OrgID | ObjID | Name | Value0 | Value1 | Value2 | ... | Value500 |
1001 | 10 | 001 | user name | uid001 | zhangsan | 18 | ... | |
1002 | 10 | 002 | order name | oid002 | 100.0 | ... |
5. 参考
官网域名: https://login.salesforce.com/
- https://trailhead.salesforce.com/modules/data_security/units/data_security_overview
- https://developer.salesforce.com/docs/atlas.en-us.212.0.securityImplGuide.meta/securityImplGuide/
Salesforce 数据安全简介 https://www.jianshu.com/p/bfab4b654183
Salesforce 入门
其他系统的数据权限机制
1. Alfresco
产品功能: Alfresco 是一款开源的企业内容管理系统(ECMS), 为企业提供了日常的文档管理, 协同工作, 工作记录管理, 知识管理, 网络内容管理, 图片管理等多种功能.
数据权限: 可以对每个页面设置用户的访问和操作权限
设计思路:
1)权限设计: 权限粒度细化到对象级别, 又将权限分为 18 种基本权限. 在这 18 种基本权限上, 又可以扩展多个权限集.
权限集名称 | 描述 | 包含元子权限 |
---|---|---|
Read | 读权限 | ReadProperties:读对象的元数据 ReadChildren:读下级节点 ReadContent:读对象内容 |
Write | 写权限 | WriteProperties:写对象的元数据 WriteContent:写对象内容 |
Delete | 删除权限 | DeleteNode:删除对象 DeleteChildren:删除下级对象 |
AddChildren | 添加子节点权限 | CreateChildren:创建下级对象 LinkChildren:将其他对象挂接到当前对象下 |
Execute | 执行权限 | ExecuteContent:执行对象内容 |
CheckIn | 签入权限 | Unlock:对象解锁 |
CheckOut | 签出权限 | Lock:对象加锁 |
CancelCheckOut | 取消签出权限 | Unlock:对象加锁 |
在以上 8 种常用权限集的基本上, 又可以扩展多个角色权限集:
角色权限集 | 描述 | 包含的子权限集 |
---|---|---|
Consumer | 使用者 | Read |
Editor | 参与者 | Consumer,Write,CheckOut,ReadPermissions |
Contributor | 协调员 | Consumer,AddChildren,ReadPermissions |
Collaborator | 合作者 | Editor,Contributor |
Coordinator | 系统管理员 | 所有权限 |
Administrator | 超级管理员 | 所有权限 |
RecordAdministrator | 记录管理员 | ReadProperties,ReadChildren,WriteProperties,ReadContent,DeleteChildren,CreateChildren,LinkChildren,DeleteAssociations,CreateAssociations |
2)用户, 组的设计: 用户可以隶属于多个组, 一个组也可以包括多个成员(组和用户)
3)ACL(访问控制表)机制: 通过 ACL 机制实现对文档的权限控制. ACL 包含多个用户, 组的访问权限, 如下表:
成员名(组或用户) | 角色权限集名 |
---|---|
Group1 | Consumer |
User1 | Editor |
User2 | Read |
注: Group1 组中的所有成员拥有所在组的权限.
4)权限机制设计: 内容库中的每一个对象 (文件夹, 文件等) 都关系一个 ACL 对象. 当用户访问内容库的对象时, 先根据该对象对应的 ACL 里查找当前用户拥有的该对象的权限, 然后判断当前用户是否拥有操作该对象的相关权限, 从而实现内容库对象的权限管理.
Alfresco 中的权限继承机制允许内容库对象继承父级节点的权限, 因此, 在对象创建的时候不必为每一个对象分配 ACL. 只要为目录结构分配好权限, 在对象创建以后默认继承父级节点权限. 通过用户, 组, ACL 的灵活配置, 可以实现复杂的内容安全控制.
5)权限机制的具体实现: 在底层把对象的操作规定了一个接口: NodeService. 将对象的各种操作抽象为几种基本方法, 如: getProperties(), setProperties(). 将这些方法进行拦截, 拦截的工作是通过当前操作用户, 当前操作的对象 id, 当前执行的操作, 判断是否可以调用该方法, 从而实现在底层实现对对象权限的控制.
参考:
Alfresco 权限机制 http://mimload.iteye.com/blog/680460
2. Oracle VPD
产品功能: VPD(Virtual Private Database)是从数据库层面实现数据访问控制的一种成熟技术, 归属 Oracle security 框架下. 通过 VPD, 银行便可以确保客户只看到他们自己的帐户, 电信公司可以安全地隔离客户记录, HR 应用程序可以支持复杂的员工记录数据访问原则.
如何使用:
VPD 是介于用户 SQL 语句和实际执行对象之间的介质层. SQL 语句在执行前, 会自动被拦截并进行额外处理, 处理结果往往是在 where 语句中添加特殊的条件式.
将一个或多个安全策略与表或视图关联, 当对带安全策略的表访问 (select/insert/update/delete) 时, 数据库将调用一个实施该策略的函数. 策略函数返回一个访问条件(where 子句), 即谓词. 应用程序将它附加到用户的 SQL 语句, 从而动态修改用户的数据访问权限. 如下面例子所示: 如果执行 select * from t_policy 语句, 则可以使用 VPD 添加 where t2 not in (10) 子句:
(1)建立测试数据表(t_policy):
- CREATE TABLE T_POLICY
- (
- T1 VARCHAR2(10 BYTE),
- T2 NUMBER(10)
- );
- insert into t_policy values('a',10);
- insert into t_policy values('b',20);
- insert into t_policy values('c',30);
- commit;
(2)建立 VPD 需要的策略, 这里的名字是: Fn_GetPolicy
- CREATE OR REPLACE function Fn_GetPolicy(P_Schema In Varchar2,P_Object In Varchar2) return varchar2 is
- Result varchar2(1000);
- begin
- Result:='t2 not in (10)'; -- t2 != 10
- return(Result);
- end Fn_GetPolicy;
(3)将策略与需要保护的表进行关联:
- declare
- Begin
- Dbms_Rls.Add_Policy(
Object_Schema =>'niegc', -- 数据表 (或视图) 所在的 Schema 名称
Object_Name =>'T_Policy', -- 数据表 (或视图) 的名称
Policy_Name =>'T_TestPolicy', --POLICY 的名称, 主要用于将来对 Policy 的管理
Function_Schema =>'NIEGC', -- 返回 Where 子句的函数所在 Schema 名称
Policy_Function =>'Fn_GetPolicy', -- 返回 Where 子句的函数名称
Statement_Types =>'Select,Insert,Update,Delete', -- 要使用该 Policy 的 DML 类型, 如'Select,Insert,Update,Delete'
Update_Check =>True, -- 仅适用于 Statement_Type 为'Insert,Update', 值为'True'或'False'. 如果为'True', 则用户插入的值不符合 Policy_Function 返回条件时, 该 DML 执行返回错误信息.
Enable =>True -- 是否启用, 值为'True'或'False'
);
end;
(4)验证 VPD 效果
执行用户 SQL:
select * from t_policy;
此时结果会少了 t2=10 这项
参考:
Oracle VPD 实现数据细粒度访问 https://blog.csdn.net/dnnyyq/article/details/5214641
Oracle VPD 详解 https://www.2cto.com/database/201609/549526.html
来源: https://www.cnblogs.com/butterfly100/p/8981747.html