在前面有关如何使用kbmMW创建REST服务器的基础上,现在已经到了考虑该如何控制用户的访问。什么是访问管理?就是“允许谁做什么"的问题。

显然,这个世界中存在数据,应该保护他而不被未授权的人/进程来读取,创建或更改。反过来说,这些数据应该得到保护,只有信任的人/进程才可以访问。另外,有的数据可以被人或进程来访问,但不允许被修改等等。

幸运的是,kbmMW内置了一些功能来解决上面的问题,核心是TkbmMWAuthorizationManager类。

首先在main form中添加一个TkbmMWAuthorizationManager(前文中的Unit7单元)。

我们可以单独使用授权管理器(authorization manager),但通常是通过kbmMWServer实例使用他,所以,将kbmMWServer1.AuthorizationManager属性设置为kbmMWAuthorizationManager1,
这样,授权管理器(authorization manager)将检查每次对应用程序服务器的访问权限。

kbmMW授权管理器是一个可理解为下面主题的实体:

  •     resource(资源)
  •     actor(演员)
  •     role(角色)
  •     authorization(授权)
  •     constraint(约束)
  •     login(登录)

resource(资源)基本上是你要为其添加某种保护的任意内容,它可以是数据库相关的,也可以是一个特定的对象,或者是你希望的功能或服务仅按你预期的方式处理,由你授予访问权限的人/进程处理。资源可以按资源树分组,允许访问其中一个资源,则自动允许访问该资源下的子资源。

actor通常是一个人(或一个人的登录凭证),一个过程或其他标识“某人”的人,他们想要访问您的资源。

role是一种对一般访问模式进行分类的方法。图书馆中的role可能是图书管理员,管理员和借用者。银行中的role可以是客户,出纳员,职员,管理员等等。这个想法是每个role对各种资源都有不同的访问权限。actor通常至少会被赋予一个role。actor可以拥有不同的role,例如:取决于actor登录的方式或来自哪里。

authorization是作为参与者或特定资源上的role运行的“许可”。authorization可以是否定的,如拒绝对特定资源及其子树的参与者或role访问。

constraint(约束)是对授权或登录的限制。授权可能仅在特定时间范围内有效,或者允许从特定设备等访问,或者登录只能在白天等进行。

login(登录)是actor/password和登录令牌之间的匹配。当actor试图登录时,系统会验证登录名,密码,请求的角色以及与登录相关的任何约束。只有在检查完所有内容并允许登录后,才会发出令牌(Token), 对基于kbmMW的服务器发出的每个请求,actor /user/process需要发送Token。

综上所述,让我们来定义两个想要访问REST服务器的角色(role),并将它们命名为“Reader”和“ReadWriter”,但由于kbmMW对角色命名(以及角色和资源)没有任何限制,只要名称在其类别中是唯一的,我们就可以为它们命名(角色,演员,资源)。

  •     Reader
  •     ReadWriter

用代码来定义上面说的两个角色(role)Reader与ReadWriter(可以写在main form的OnCreate事件中):

 kbmMWAuthorizationManager1.AddRole('READER');
kbmMWAuthorizationManager1.AddRole('READWRITER');

我们还需要告诉授权管理器哪些参与者存在,以便它可以与演员匹配以尝试登录。

简单的方法是将它们预定义给授权管理器。同样,可以写在main form的OnCreate事件中,也可以写在第一次访问服务器之前的其他地方。按你的实际情况,利用数据库或配置文件或LDAP等定义actor。

kbmMWAuthorizationManager1.AddActor('HANS','HANSPASSWORD','READER');
kbmMWAuthorizationManager1.AddActor('CHRISTINE','CHRISTINEPASSWORD','READWRITER');

这里定义了两个参与者的密码,如果他们没有特别要求不同的角色,他们应该在登录时确定了扮演的角色。
有可能不预定义actor,取而代之使用事件处理程序,即通过kbmMWAuthorizationManager1实例的OnLogin事件验证它们是否存在于不同的系统中。

procedure TForm7.kbmMWAuthorizationManager1Login(Sender: TObject;
const AActorName, ARoleName: string; var APassPhrase: string;
var AActor: TkbmMWAuthorizationActor; var ARole: TkbmMWAuthorizationRole;
var AMessage: string);
begin
...
end;

一个AActorName与其请求的角色名称由ARoleName提供。可选地,如果actor name 为kbmMW已知,则还可以提供actor实例。如果没有,AActor为nil,如果你知道actor则必须由你创建。

ARole可能是nil,如果它是一个被请求的未知角色。可以选择通过返回新创建的TkbmMWAuthorizationRole实例来动态建立角色。但请记住在返回之前,将任何新创建的actor或角色实例添加到kbmMWAuthorizationManagers的Actors和Roles列表属性中。

APassword将包含登录尝试时提供的密码。您可以动态修改它(例如将其更改为SHA256 hash,这样,授权管理器中将不存储明文密码)。
如果您为AActor或ARole返回nil ,则表示登录失败。如果需要,可以在AMessage参数中提供说明。

让我们继续为这个例子,定义一个简单的actor。

现在我们已定义了actors和roles,授权管理器已准备好处理登录尝试。

登录只有一种方法,即通过调用授权管理器的Login方法。例如,可以从REST服务中的新REST函数调用它。

另一种方法是让kbmMW自动检测登录尝试,并为您调用Login方法。为此,请将kbmMWAutorizationManager1Options属性设置为[ mwaoAutoLogin ]。

您可能还记得,对kbmMW服务器的所有请求都必须附带一个标识有效登录的令牌。如果该令牌不可用,则使用从调用者传递的任何用户名/密码作为登录尝试的数据触发kbmMW(设置了mwaoAutoLogin),并在登录成功时将令牌返回给被调用者。

由于REST服务器本质上是一个Web服务器,遵循HTTP协议标准,当kbmMW检测到无效(或不存在)登录时会发生什么,kbmMW将引发一个EkbmMWAuthException,反过来(当调用来自REST时) streamformat),将被转换为HTTP错误401,呈现给调用者。实际上,如果您在业务代码中的任何位置引发该异常并且您自己不管理它,它将自动作为401转发给调用者。

这将提示大多数浏览器提供登录对话框,其中可以输入用户名/密码,然后下一次调用回服务器,将包括该登录信息。kbmMW将自动检测并使用它。

所以我们有演员,角色和登录。现在我们需要确定我们拥有哪些资源。资源可以是您要标记唯一名称的任何内容。

大多数情况下,将REST方法定义为资源是有意义的。使用kbmMW_Auth属性,让我们在smart service中非常容易完成。我们拥有操作和检索联系人的功能(Unit8)。

[kbmMW_Service('name:MyREST, flags:[listed]')]
[kbmMW_Rest('path:/MyREST')]
TkbmMWCustomSmartService8 = class(TkbmMWCustomSmartService)
public
[kbmMW_Auth('role:[READER,READWRITER], grant:true')]
[kbmMW_Rest('method:get, path:helloworld, anonymousResult:true')]
[kbmMW_Method]
function HelloWorld:TMyResult; [kbmMW_Auth('role:[READER,READWRITER], grant:true')]
[kbmMW_Rest('method:get, path:contacts, anonymousResult:true')]
function GetContacts:TObjectList; [kbmMW_Auth('role:[READWRITER], grant:true')]
[kbmMW_Rest('method:put, path:addcontact')]
function AddContact([kbmMW_Rest('value:"{$name}"')] const AName:string;
[kbmMW_Rest('value:"{$address}"')] const AAddress:string;
[kbmMW_Rest('value:"{$zipcode}"')] const AZipCode:string;
[kbmMW_Rest('value:"{$city}"')] const ACity:string):string; overload; [kbmMW_Auth('role:[READWRITER], grant:true')]
[kbmMW_Rest('method:get, path:"addcontact/{name}"')]
function AddContact([kbmMW_Rest('value:"{name}"')] const AName:string):string; overload; [kbmMW_Auth('role:[READWRITER], grant:true')]
[kbmMW_Rest('method:delete, path:"contact/{id}"')]
function DeleteContact([kbmMW_Rest('value:"{id}"')] const AID:string):boolean;
end;

幕后发生的事情是kbmMW自动为这些函数定义资源名称:MyREST..AddContectMyREST..GetContacts等。

额外注意一点:如果我们为定义的Service定义了版本,当我们建立他时,在中间应放一个“."。

如你所见,资源名称只是一个字符串,您可以自己定义所需的所有资源,但如果你用smart service,可以用上面的格式自动定义资源名称。

kbmMW还将自动要求授权管理员在任何客户端的呼叫时验证是否允许使用资源。

您可以选择通过手动调用授权管理器来进行更细粒度的授权,以验证调用,如下所示:

var
res:TkbmMWAuthorizationStatus;
sMessage:string;
begin
...
res:=AuthorizationManager1.IsAuthorized(logintoken, 'YOURRESOURCENAME', sMessage);

res返回mwasAuthorizedmwasNotAuthorizedmwasConstrained  。

mwasConstained意味着授权可以在不同的情况下(不同的时间或类似的时间)给出。返回的sMessage可以更详细地解释访问被拒绝的原因。

在kbmMW智能服务(smart service)中,您可以获取登录令牌(logintoken)作为方法的参数,如下所示:

 [kbmMW_Auth('role:[READER], grant:true')]
[kbmMW_Rest('method:get, path:"someCall"')]
function SomeCall([kbmMW_Arg(mwatToken)] const AToken:string):boolean;

调用SomeCall方法时,其AToken参数包含logintoken

如果您不希望令牌成为方法调用的参数列表的一部分,您也可以在方法中访问ClientIdentity.Token属性。

现在,您的REST服务器受SSL保护,并通过登录调用其功能。

授权管理器中有许多功能,我在这里没有解释,但可以访问我们的网站http://www.components4developers.com,查找kbmMW白皮书相关部分。

原文地址:https://components4developers.blog/2017/05/26/rest-easy-with-kbmmw-4-access-management/

作者相关的博文:

使用kbmMW#1轻松实现REST

使用kbmMW#2轻松实现REST - 数据库

使用kbmMW#3 - SSL轻松实现REST

使用kbmMW#5轻松实现REST - 记录

REST easy with kbmMW #4 – Access management的更多相关文章

  1. REST easy with kbmMW #14 – DB Controlled login

    介绍 关于如何使用授权和登录管理来构建应用服务器还存在一些问题,其中之一就是用户及其角色如何在在数据库中定义.该文将解释使用TkbmMWAuthorizationManager解决此问题的一种方法.有 ...

  2. Gravitee.io Access Management 组件

    Access Management组件在Gravitee.io 主要是进行认证以及权鉴的处理,支持oauth2 以及openid connect 等协议,同时好多功能已经集成在ui 管理界面上了,还是 ...

  3. REST easy with kbmMW #3 – SSL

    我在前两篇文章中展示了“REST easy with kbmMW”文章,如何使用kbmMW制作REST服务器,以及如何使用该REST服务器轻松地从数据库返回和存储数据,所有这些都在不到30行的真实数据 ...

  4. REST easy with kbmMW #15 – Handling HTTP POST

    我被问到有关如何通过基于kbmMW智能服务(Smart Service)的REST处理POST的问题. 这篇博客文章解释了典型的POST各种形式的访问,以及如何在kbmMW中处理它们. POST变种W ...

  5. REST easy with kbmMW #1

    kbmMW 5.0支持REST服务器的开发,并且非常简单,下面看看如何实作一个REST服务器. 首先我们制作一个服务器应用程序,增加一个简单的Form,并放置kbmMW组件. 在Delphi中单击Fi ...

  6. REST easy with kbmMW #24 使用kbmMW实现JSON/XML/YAML转换成对象

    你想过没有,把一个给定的xml或json生成一个Delphi类,并通过这个类完成对xml或json的读写操作吗? 不管有没有,现在kbmMW为我们实现了,看下面这行代码: var s:string; ...

  7. REST easy with kbmMW #21 – Delphi client stubs

    在之前的博文中,我提到新的存根生成器框架具有生成Delphi客户端存根所需的功能,使得开发Delphi智能客户端非常容易,完全支持编译时的类型检查和IDE类/属性帮助. 我没想到会把它包含在即将发布的 ...

  8. REST easy with kbmMW #20 – OpenAPI and Swagger UI

    即将推出的kbmMW更新不仅是一些bug修正,同时将包含一个新的主要功能:客户端存根生成器框架. 那什么是客户端存根生成器框架呢? 他是一个基于kbmMW smart services,可以生成由各种 ...

  9. REST easy with kbmMW #17 – Database 6 – Existing databases

    kbmMW已经包含了非常精细的功能来确定和解释数据库中表的元数据. 在下一版本中,这个功能将得到进一步加强,可以导入现有数据库中的表,自动创建与表相匹配的ORM实体类. 这意味着你能够使用kbmMW的 ...

随机推荐

  1. 数组类型的退化Decay

    Decay即数组在某些情况下将退化为指针. 测试代码: #include <iostream> #include <typeinfo> template <typenam ...

  2. DEV-C++设置C++11标准

    DEV-C++默认的标准是C++98,改成C++11的方法如下: Tools -> Compiler Options -> Setting -> Code Generation -& ...

  3. C++ 在容器A中查找最后出现的容器B中的元素,并返回iterator(find_end)

    #include <iostream> // cout #include <algorithm> // find_end #include <vector> // ...

  4. bcompare Linux版 无限试用

    需要root权限.   # mv /usr/bin/bcompare /usr/bin/bcompare.real # cat /usr/bin/bcompare #!/bin/sh rm " ...

  5. Redis的介绍

    REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C语言编写.遵守B ...

  6. response.sendRedirect跳转 jsp:forward跳转

    response.sendRedirect跳转 <% response.sendRedirect("online.jsp"); %> jsp:forward跳转 < ...

  7. Go开发环境安装配置

    访问下载地址:https://golang.org/dl/ 32位系统下载go1.8.1.linux-386.tar.gz,64位系统下载go1.8.1.linux-amd64.tar.gz, 假定你 ...

  8. English trip -- VC(情景课)8 D Reading

    Listen and read. Shop Smart [smɑːt]  Employee of the Month: Sara['særə] (萨拉) Lopez(洛佩斯) Congratulati ...

  9. 『Scipy』常用方法记录

    优化器使用教程 J = lambda wb: self.get_cost_grad(wb, X, Y_one_hot) theta = self.wb_init(X,Y_one_hot) result ...

  10. centos6.5升级安装openssl1.0.2h

    最新漏洞通报: Openssl多个漏洞安全预警 2016-05-05 18:05:39 一.概述 在OpenSSL官方昨日(2016/5/3)发布的安全公告中,公开了两个新的高危漏洞CVE-2016- ...