[QSecurity]QSecurity 使用入门指南

QSecurity 是 QPlugins 的安全相关插件接口及其实现, qplugins_security.pas 定义了安全相关的接口,我们在插件中使用时,只需要引用这个接口文件就可以了。而服务的实现单元并不包含在免费开源的范围内,如果您不想自己实现,或者想参考实现,需要付费购买,价格为人民币 99.00 元。

无论是我的实现,还是您自己去实现这些接口,它的用法是一样的,所以这个入门教程适合兼容于qplugins_security 接口的所有实现。

一、查找 IQSecurityService 服务

查找 IQSecurityService 服务接口和查找普通的服务是一样的,有多种方式:

  • 如果你不知道服务的路径,那么直接通过 PluginsManager 来查找 IQSecurityService 实例即可,当然这并不是效率最高的方式,因为 PluginsManager 会遍历查找所有注册的接口及服务,以便找到它。但它是最易用的一种方式,在 Delphi 中,可以:
    var
       AService:IQSecurityService;
    begin
      AService:=PluginsManager as IQSecurityService;
      ....
    end;

    或者

    var
       AService:IQSecurityService;
    begin
      if Supports(PluginsManager ,IQSecurityService ,AService then
         begin
         ....
         end;
    end;

    或者:

    var
       AService:IQSecurityService;
    begin
      if PluginsManager.QueryInterface(IQSecurityService ,AService)=S_OK then
         begin
         ....
         end;
    end;

    当然,这几种方式本身没啥优劣之分,第一种要求服务必需已经注册才能使用,而后两种都会判定是否存在相应的接口。如果确认支持相应的服务,那就放心使用第一种方式,它在 Delphi 中最方便。

  • 如果您知道服务的路径,按注册路径查找更快一些,我实现的服务注册路径为 /Services/Security,所以像下面这样子调用:
    var
       AService:IQSecurityService;
    begin
       AService:=PluginsManager.ByPath('/Services/Security') as IQSecurityService;
       ....
    end;

二、注册自己模块的权限

对于松散耦合的应用开发来说,你永远不知道啥时候增加啥模块,而增加模块就意味着可能增加新权限项目。QPlugins Security 模块将这一步交由插件自身,“自事自知”,通过启动时注册自己的权限,然后授权模块就可以为用户进行授权。

一个简单的例子(我们继续接上面的 AService)是安全管理服务注册自己的权限:

  1. 定义权限的ID,它是一个GUID编码,你自己模块随意定义就可以,不需要关心其它模块的定义,毕竟你用 Ctrl+Shift+G 生成的随机的 GUID 编码与其它人定义重复的可能性很低。这个 ID 是你程序中检查权限的基础,一般我们会为权限进行分组,象下面的示例中,定义的是一个分组ID,两个子项权限:
    const
      // 角色及权限管理分组ID
      SID_SECURITY_GROUP: TGuid = '{110CA18E-4B52-4D75-B3F3-9C99DC2B76FE}';
      // 查看其它用户账号及权限
      SID_SECURITY_VIEW: TGuid = '{B02A4134-3563-42A0-825E-C90BB5DD031E}'; //
      // 修改其它用户账号及权限等资料
      SID_SECURITY_EDIT: TGuid = '{800896A0-E733-48BB-8CB4-857EC83F6F89}';
  2. 在插件的 initialization 里,注册权限:
    var
       ARights:IQSecurityRights;
       AService:IQSecurityService;
    begin
    with PluginsManager as IQSecurityService do
       begin
       //注册分组
       ARights:=IQSecurityRights(GetRootRight).AddGroup(SID_SECURITY_GROUP,
          '账号及权限管理', TQAccessRight.arDeny);
       //注册子权限
       ARights.AddRight(SID_SECURITY_VIEW, '查看存在的账号及角色信息', TQAccessRight.arDeny);
       ARights.AddRight(SID_SECURITY_EDIT, '管理账号、角色及其权限', TQAccessRight.arDeny);
       end;
    end;
    

    注册完成后,内存中就有了相应的权限对象。

三、判断当前用户权限

在需要判断权限的地方,通过 IQSecurityService.CanAccess 即可,比如:

with PluginsManager as IQSecurityService do
   begin
     btnView.Visible:=CanAccess(SID_SECURITY_VIEW);
     btnEdit.Visible:=CanAccess(SID_SECURITY_EDIT);
   end;

QSecurity 用户权限检验的规则说明如下:

  1. 用户如果未登录,则根据权限对象默认权限定义返回;如果默认权限不是明确的允许或拒绝,则继承自全局的默认权限。在我的实现中,它是拒绝。如果你确定某个权限默认开通,那你可以在上一步注册权限时,将默认权限设置为 arAllow 即可。
  2. 如果用户已经登录,则根据以下规则执行:
    (1)在当前登录用户级别上,明确了允许还是拒绝,则返回明确的结果;如果没有,则检查有没有明确允许其父权限分组定义,如果仍没有,则遍历自己父角色执行同样的操作,以最终确定权限。
    (2)如果当前用户多个父角色对同一对象的访问权限有冲突,那么按用户未登录时,检查权限的规则来处理。

四、注消权限注册

QSecurity 不支持权限的注销,也不需要插件释放相关的权限对象实例。

五、对插件修改当前用户权限的支持

出于安全原因,QSecurity 不允许其它插件去修改权限,相关的接口也不公开给其它插件使用。要修改当前用户的权限,通过 IQSecurityService 的 Config 接口来打开权限管理界面来修改。如果当前登录用户权限发生变动,还会发送 SNotify_RightsChanged 通知。

更多接口说明,请参考 qplugins_security 中相关接口函数的说明。

分享到: