kbmMW授权管理解析(The kbmMW Authorization manager explained)

Posted kinglandsoft

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kbmMW授权管理解析(The kbmMW Authorization manager explained)相关的知识,希望对你有一定的参考价值。

从kbmMW v.4.40开始,引入了一个新的非常灵活的授权管理器。

它的目的是为开发人员提供为用户定义资源权限的功能,这是一个可选功能,将现有的授权事件驱动方案内置到kbmMW中,使授权开发任务更容易实现。

据说一张图片值1000字......让我们看看是不是这样:

技术分享图片

上述图显示了一个典型的用户如何与应用服务器(绿色的东西)内的功能相互作用。 此外,它还显示了新的身份验证管理器如何添加到应用程序服务器,以及它如何在内部运行。

基于这张图,我还是要用1000多的文字来解释这是怎么回事。

首先:什么是你感兴趣的呢?

如果您计划或已经为一个或多个客户端提供本地集中功能,那么您可能会对此感兴趣,并且所提供的功能应取决于客户端的确切位置以及客户端的行为方式。

这是安全性的问题。 安全性通常作为客户端中的信任方案实现,或者作为数据库中的强制功能实现。

客户的信任为基础的安全是基本一致的,因为没有安全性可言。 如果您的客户端应用程序必须表现良好以确保您的数据不受错误影响,那么梦想一个场景并不需要太多幻想,其中该客户端软件(至少部分地)被另一个不那么好的行为客户端替换。 此外,它还很难添加另一个客户端应用程序(例如移动应用程序),它可以安全地访问和操作中央存储上的功能和数据; 因为客户端需要实现与第一个客户端相同的所有安全层,这意味着代码重用很少,并且大量复制/粘贴可能导致的安全漏洞。

数据库强制安全性要好得多,因为实际上有一个活动的集中式层负责决定客户端可以做什么而不用处理数据库中的数据。 但是,如果您执行的操作不仅仅是从数据库访问相当简单的数据结构,那么如果数据库实际上包含自己的编程语言,您将不得不求助于特定于数据库的编程语言,如TransactSQL,PL / SQL等,或者 您将把功能移动到客户端,在上面的段落中指出这是一个次优的解决方案。

更好的解决方案是使用Delphi或C ++作为编程语言,将所有开发人员/业务定义的代码(如报告生成,数据导出/导入,计算等)放在开发人员控制器应用程序服务器上。换句话说,做一个3层的解决方案:客户端,应用服务器,数据库服务器。 这为您提供了最高的灵活性,更轻松地支持其他客户端类型,同时仍然维护一个可以强制执行安全措施的层。

kbmMW总是有事件和功能来处理请求的授权,但开发人员有责任编写实际代码来执行繁琐任务。

现在,随着kbmMW v4.40发布,提供了一个名为TkbmMWAuthorizationManager新组件。

还有之后的安全保护功能,可以定义多种“模式”。 我们选择使用一个非常灵活的,基于3个定义:

  • Actors
  • Roles
  • Resources

一个Actor通常是同一个用户,具有一个登录名和口令,以及默认的角色(role)。 Actor也不一定为现实中的用户,它也可以由应用程序本身使用,例如允许应用程序在特殊情况下充当特定的Actor。

一个Actor可以有不同的“帽子”..基于系统中不同的角色(role)运行。

Resource是基本的东西,你作为开发商,希望把某种需要保护的东西命名。 例如,它可以是特定的kbmMW服务,或kbmMW服务中的特定功能,但由于开发人员100%负责选择资源的命名方案,开发人员可以想到的任何东西都可以成为资源(resource)。

基于这三个定义,开发人员就可以定义授权了。 授权指属于特定角色(role)的用户(actor)是否可以访问特定资源。

此外,授权可能仅在特定时间段内有效(例如上午9点至下午3点,或仅周三,或仅4月1日等),并且可能仅在请求来自特定物理客户端时才有效。 在kbmMW中,我们称之为约束的限制。授权可标记有零个或多个约束。

我们已经谈了很多关于actor。 但在现实世界中,我们拥有用户,这些用户需要进行身份验证并被识别为已定义的角色之一。 为此,我们在kbmMW的授权系统中有最终的子组件:登录。

一个登录是验证已知列表中的actor的用户名/密码。 如果用户名/密码通过验证,则会根据任何已定义的登录约束做进一步检查,登录约束定义了基于例如时间或客户端位置等可能不允许登录的特殊情况。

现在,我们为演示应用服务器增加安全功能。

技术分享图片

如上图,拖放一个TkbmMWAuthorizationManager到Form上,然后设置kbmMWServer的属性AuthorizationManager指向刚拖放的组件。现在,kbmMWServer就知道在适当的时候去请求他的授权管理器为他处理授权了。

什么是适当的时候? 当未登录到系统的用户尝试访问任何内容时,或者当已登录的用户尝试访问服务标志表明需要授权运行的服务时。 这可以在通过服务向导创建kbmMW服务时定义,但也可以在之后定义。

让我们看一个演示的查询服务(Query Service),即从SQLite数据库向客户端返回数据的查询服务。

技术分享图片

 

unit Unit2;    

interface    

uses    
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  kbmMWServer, kbmMWQueryService, Db, kbmMemTable, kbmMWCustomConnectionPool,
  kbmMWCustomDataset, kbmMemCSVStreamFormat, kbmMWSecurity,
  kbmMWBinaryStreamFormat, kbmMWStreamFormat, kbmMWResolvers, kbmMWSQLite,
  kbmMWServiceUtils;
type    
   TTestQuery = class(TkbmMWQueryService)
      kbmMWBinaryStreamFormat1: TkbmMWBinaryStreamFormat;               
      ClientSideQuery: TkbmMWSQLiteQuery;
      ALL_EVENTS: TkbmMWSQLiteQuery;
      SELECTED_EVENT: TkbmMWSQLiteQuery; 
      kbmMWSQLiteResolver1: TkbmMWSQLiteResolver;  
      SELECTED_SPECIES: TkbmMWSQLiteQuery;  
      ALL_SPECIES: TkbmMWSQLiteQuery;  
  private 
     { Private declarations }  
  public  
     { Public declarations }  
    class function GetFlags:TkbmMWServiceFlags; override;  
  end;  

var  
   TestQuery: TTestQuery;  

implementation  

uses Unit1;  

{$R *.DFM}  

class function TTestQuery.GetFlags:TkbmMWServiceFlags;  
begin  
     Result:=[mwsfListed,mwsfRunRequireAuth];  
end;  

end. 

没有太多的代码,除GetFlags类函数返回一组服务标志。 通过确保mwsfRunRequireAuth包含在服务标志集中,从而告诉kbmMWServer只允许对此查询服务中的所有功能都要经过授权才可以调用。

现在,需要决定我们的授权方案应该如何定义了。

可以直接在应用程序服务器中定义Actor,也可以在需要时通过从外部源(例如在数据库中定义的用户)请求授权来动态定义。

角色通常直接在应用程序服务器中定义,资源和授权也是如此,尽管它实际上可以保存和加载XML中的所有内容,从而允许对定义进行外部更改。

为简单起见,我们选择此应用程序服务器已知Gertrude和Franz作为actor,Administrator和User作为两个角色。

作为简单的例子,可以在MainForm的OnCreate事件中定义,当然也可以在其他地方定义,但必须遵循,在定义前不能执行授权给任何人。

procedure TForm1.FormCreate(Sender: TObject);  
var  
   sd:TkbmMWCustomServiceDefinition;  
begin  
     sd:=kbmMWServer1.RegisterServiceByName(KBMMW_QUERY,TTestQuery,false); 
       
kbmMWAuthorizationManager1.AddRole(Administrator,0);       
kbmMWAuthorizationManager1.AddRole(User,0); 
     kbmMWAuthorizationManager1.AddActor(
Gertrude,GertrudesPassword,User);       
kbmMWAuthorizationManager1.AddActor(Franz,FranzPassword,Administrator); 
end

 加入两个角色(Role),两个演员(Actor)。每个演员(Actor)的定义有一个默认角色(Role)。 任何actor都可以通过除默认角色之外的其他角色请求访问。 如果允许actor通过该角色访问资源,则仅取决于我们需要很快定义的授权。

接下来,需要弄清楚我们的应用服务器哪些资源需要保护,虽然已经定义了TTestQuery服务上的功能需要授权,但并不具体。

如果我们让kbmMW完全自动地处理授权,kbmMW定义要由包含所请求的服务名称,点和所请求的函数名称的字符串标识的资源。

在我们的示例中,通过RegisterServiceByName将查询服务注册标识为“KBMMW_QUERY”,客户端请求查询服务时将使用该标识,并且客户端可以使用查询服务支持的功能,即“QUERY”,“DEFINITIONS”,“EXECUTE”,“RESOLVE”,“INVENTORY”或“METADATA”这些功能。

这意味着当客户端打开查询时,至少会在服务上执行“QUERY”功能。

如果您使用自己的自定义服务,则可能在服务端定义了大量自定义函数,而这些函数将是你的客户端要使用的函数。

在默认授权模式下,构造的资源名称为“KBMMW_QUERY.QUERY”,“KBMMW_QUERY.DEFINITIONS”,“KBMMW_QUERY.EXECUTE”等。

资源是由授权管理器实例的方法AddResource定义,必须提供资源名称和可选的父资源引用。我们可以使用定义资源树的功能,以便在我们为用户定义授权时最大限度地减少代码量。

var
   adminResources,userResources:TkbmMWAuthorizationResource;  
… 
   adminResources:=kbmMWAuthorizationManager1.AddResource(AdminResources,nil);
userResources:=kbmMWAuthorizationManager1.AddResource(UserResources,adminResources);         
kbmMWAuthorizationManager1.AddResource(KBMMW_QUERY.QUERY,userResources);       
kbmMWAuthorizationManager1.AddResource(KBMMW_QUERY.DEFINITIONS,userResources);       
kbmMWAuthorizationManager1.AddResource(KBMMW_QUERY.EXECUTE,userResources);       
kbmMWAuthorizationManager1.AddResource(KBMMW_QUERY.INVENTORY,userResources);       
kbmMWAuthorizationManager1.AddResource(KBMMW_QUERY.METADATA,userResources);       
kbmMWAuthorizationManager1.AddResource(KBMMW_QUERY.RESOLVE,adminResources); 

我们已经定义了两个虚拟资源。一个名为AdminResources,没有父资源,另一个名为UserResources,其AdminResources为父资源。 换句话说,UserResources是AdminResources的子集,因此允许访问AdminResources的actor/role也可以访问UserResources。

技术分享图片

现在用下面的代码定义授权:

kbmMWAuthorizationManager1.Grant(‘‘,User,UserResources,[mwapExecute]);
kbmMWAuthorizationManager1.Grant(‘‘,Administrator,AdminResources,[mwapExecute]); 

第一个语句授予任何扮演‘User‘角色的actor并在‘UserResources‘组中请求资源的授权,具有mwapExecute(执行请求)的权限。

由于可以明确的指定actor名称,而不是空字符串,因此您可以根据需要为特定人员制作非常精确的授权。 但是,在正常情况下,仅仅授权角色资源就更清晰了。

除了Grant之外,您还可以使用与上面相同的语法,仅使用Deny方法拒绝授权。 但是,它应该很少需要,如果是这样,它可以表明您应该检查资源树和角色定义,看看它们是否可以以不同的方式排列,以更好地满足您的授权需求。

如果任何客户端尝试连接到应用程序服务器并从查询服务请求数据,则将始终拒绝访问它们。 为什么?我们还是很怀念登录客户端。

下图为登录流程:

技术分享图片

最简单的方法是让kbmMW应用服务器完全自动处理的登录流程。 我们可以通过将Options属性设置为包含mwaoAutoLogin来实现。

技术分享图片

接下来的事情就是让客户端提供相关的用户名和密码。

这有多种方法,其中之一是使用TkbmMWSimpleClient组件,通过他的实例提供用户名与密码,然后所有的TkbmMWClientQuery组件通过Client属性使用TkbmMWSimpleClient组件实例,从而取代TkbmMWClientQuery内部使用的Client实例。

如果它是一个多线程客户端应用程序,更好的方法是在客户端查询组件上将ClientAsTemplate设置为true,并确保在打开任何查询之前发生的第一件事是通过SimpleClient执行请求(它可能是一个虚拟的“LOGON”服务器端功能)的调用。 该函数不必执行任何操作,但它确保在查询开始触发之前已发生kbmMW登录过程,并确保从服务器提供登录标记。

本文只涉及了什么可以与授权管理器来完成授权的基本概念,还没有讨论如何在实际数据表上添加更细粒度的授权,如何在不使用后登录超时,如何保存和加载XML的完整授权设置,如何将约束添加到登录和授权,如何允许匿名/未知用户访问特定功能,如何基于外部资源(例如数据库)动态定义角色等。

但是这一切都支持用新的授权管理机制来实现,至少我是希望能够更好地了解你的需求。

 















以上是关于kbmMW授权管理解析(The kbmMW Authorization manager explained)的主要内容,如果未能解决你的问题,请参考以下文章

kbmmw 中的进程管理小工具

简介kbmmw 5 里面的日志备份功能

kbmmw 中虚拟文件操作入门

在指定时间干,必须干(kbmmw 中的事件调度)

使用kbmMW调试内存泄漏

kbmmw ORM 对象定义语法简析