在前面有關如何使用kbmMW建立REST服務器的基礎上,如今已經到了考慮該如何控制用戶的訪問。什麼是訪問管理?就是「容許誰作什麼"的問題。
顯然,這個世界中存在數據,應該保護他而不被未受權的人/進程來讀取,建立或更改。反過來講,這些數據應該獲得保護,只有信任的人/進程才能夠訪問。另外,有的數據能夠被人或進程來訪問,但不容許被修改等等。
幸運的是,kbmMW內置了一些功能來解決上面的問題,核心是TkbmMWAuthorizationManager類。
首先在main form中添加一個TkbmMWAuthorizationManager(前文中的Unit7單元)。html
咱們能夠單獨使用受權管理器(authorization manager),但一般是經過kbmMWServer實例使用他,因此,將kbmMWServer1.AuthorizationManager屬性設置爲kbmMWAuthorizationManager1,
這樣,受權管理器(authorization manager)將檢查每次對應用程序服務器的訪問權限。數據庫
kbmMW受權管理器是一個可理解爲下面主題的實體:瀏覽器
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對角色命名(以及角色和資源)沒有任何限制,只要名稱在其類別中是惟一的,咱們就能夠爲它們命名(角色,演員,資源)。服務器
用代碼來定義上面說的兩個角色(role)Reader與ReadWriter(能夠寫在main form的OnCreate事件中):wordpress
kbmMWAuthorizationManager1.AddRole('READER'); kbmMWAuthorizationManager1.AddRole('READWRITER');
咱們還須要告訴受權管理器哪些參與者存在,以便它能夠與演員匹配以嘗試登陸。函數
簡單的方法是將它們預約義給受權管理器。一樣,能夠寫在main form的OnCreate事件中,也能夠寫在第一次訪問服務器以前的其餘地方。按你的實際狀況,利用數據庫或配置文件或LDAP等定義actor。網站
kbmMWAuthorizationManager1.AddActor('HANS','HANSPASSWORD','READER'); kbmMWAuthorizationManager1.AddActor('CHRISTINE','CHRISTINEPASSWORD','READWRITER');
這裏定義了兩個參與者的密碼,若是他們沒有特別要求不一樣的角色,他們應該在登陸時肯定了扮演的角色。
有可能不預約義actor,取而代之使用事件處理程序,即經過kbmMWAuthorizationManager1實例的OnLogin事件驗證它們是否存在於不一樣的系統中。spa
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則必須由你建立。rest
ARole多是nil,若是它是一個被請求的未知角色。能夠選擇經過返回新建立的TkbmMWAuthorizationRole實例來動態創建角色。但請記住在返回以前,將任何新建立的actor或角色實例添加到kbmMWAuthorizationManagers的Actors和Roles列表屬性中。code
APassword將包含登陸嘗試時提供的密碼。您能夠動態修改它(例如將其更改成SHA256 hash,這樣,受權管理器中將不存儲明文密碼)。
若是您爲AActor或ARole返回nil ,則表示登陸失敗。若是須要,能夠在AMessage參數中提供說明。
讓咱們繼續爲這個例子,定義一個簡單的actor。
如今咱們已定義了actors和roles,受權管理器已準備好處理登陸嘗試。
登陸只有一種方法,即經過調用受權管理器的Login方法。例如,能夠從REST服務中的新REST函數調用它。
另外一種方法是讓kbmMW自動檢測登陸嘗試,併爲您調用Login方法。爲此,請將kbmMWAutorizationManager1的Options屬性設置爲[ 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..AddContect,MyREST..GetContacts等。
額外注意一點:若是咱們爲定義的Service定義了版本,當咱們創建他時,在中間應放一個「."。
如你所見,資源名稱只是一個字符串,您能夠本身定義所需的全部資源,但若是你用smart service,能夠用上面的格式自動定義資源名稱。
kbmMW還將自動要求受權管理員在任何客戶端的呼叫時驗證是否容許使用資源。
您能夠選擇經過手動調用受權管理器來進行更細粒度的受權,以驗證調用,以下所示:
var res:TkbmMWAuthorizationStatus; sMessage:string; begin ... res:=AuthorizationManager1.IsAuthorized(logintoken, 'YOURRESOURCENAME', sMessage);
res返回mwasAuthorized,mwasNotAuthorized或mwasConstrained 。
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/
做者相關的博文: