RLS浅析

AX为了处理记录集权限,增加了Record Level Security功能,可以通过管理->设置->安全性->记录级安全性 这个窗体设置。本文尝试分析RLS的实现方法并针对一些常见的问题说一下自己的看法。
1.实现方法:
AX针对记录级权限的实现方式很简单,大体翻翻管理->设置->安全性->记录级安全性这个窗体的代码就可以看到了,其中控件 查询的clicked方法要特别注意,该方法的源代码如下:

Code

通过这段代码我们可以清晰地看到RLS的相关记录信息都放到了表SysRecordLevelSecurity中,该表在AOT中没有,只能通过数据库去查看其字段的情况,主要包含如下字段:
TableId:表的ID
GroupId:用户组ID
RESTRICTION:记录级权限的内容,该字段是Image类型的,对应X++里的Container类型
RESTRICTION的内容实际上就是QueryRun对象通过pack方法序列化成二进制的结果。
具体是怎么执行的那?由于这部分代码是有Kernel执行的,所以我们无从查起,只能通过跟踪SQL的方式猜测起运行原理。
AX执行查询有几种方式,一种是通过对象化的QueryRun等对象,一种是通过内置的X++语法直接执行,这两种方式下都支持RLS,QueryRun和Query都有recordLevelSecurity这个属性,在默认情况下该属性的值是true,而表变量也有recordLevelSecurity这个属性,在默认情况下是false,可以根据需要开启或者关闭记录级权限控制。我们通过X++语法的方式执行SQL查询,假定我们添加了当前组针对CustTable的记录级权限,只让属于当前用户组的用户看到4000..4008的记录。

Code

通过SQL跟踪,我们可以看到在执行上述语句时,有两条SQL语句值得关注:

Code

Code

从上述语句我们可以猜测Kernel实现的思路:

1.根据当前用户所属的组ID和当前所在公司的ID从表SysRecordLevelSecurity中查找是否有匹配的记录;
2.从查询的结果中找到当前查询涉及的表CustTable对应的RESTRICTION值;
3.由于RESTRICTION是QueryRun对象序列化的结果,自然可以根据它反序列化出QuerRun对象从而找到查询条件;
4.将查询条件添加到针对表CustTable的查询语句中。
OK,以上只是我的猜测,不见得准确。
2.常见的问题
A.RLS会不会自动关联1:n和n:1关系?
举例来说,我对表CustTable设置了只允许某个组查看4000..4008的记录,那么表CustTrans是不是也可以自动过滤出只有4000..4008的记录?从上述实现的原理来看,显然是不行的,因为他们都是针对单个表添加查询条件的,并没有查看与之关联的表。
B.如何将一个组的RLS设置拷贝给另一个组?

由于只涉及到一个表SysRecordLevelSecurity,问题就很简单了,无非是记录的拷贝而已。

Code

上述代码是将组RLS1的行记录设置拷贝给组RLS2。

OK,本文试图对RLS的实现原理加以阐述,并列举了我在使用AX过程中经常遇到的两个问题,限于我的水平,错误在所难免,还望高手赐教。

原文地址:https://www.cnblogs.com/Farseer1215/p/1319862.html