簡體   English   中英

如何在Datasnap Server Methods單元中獲取經過身份驗證的用戶名和密碼?

[英]How can I obtain the authenticated Username and Password in a Datasnap Server Methods unit?

一旦使用正確的參數名稱(在Delphi Datasnap Server用戶身份驗證中說明),Datasnap身份驗證非常簡單。 下一個問題是在使用FireDAC數據庫連接時能夠使用這些相同的憑據。 答案似乎隱含在最有效的方式將SQL登錄憑據傳遞給Delphi Datasnap服務器? 雖然“簡單轉發”並沒有真正解釋如何完成代碼。 此外,這些憑據應該作為用於登錄Datasnap服務器的相同憑據進行身份驗證。 這樣可以防止在數據庫級別進行模擬。

到目前為止,我還沒有找到任何方法從Server Methods單元中以編程方式獲取當前的Datasnap用戶憑據。 例如,在BeforeConnect事件中。 我正在使用的代碼是使用會話生命周期使用Delphi XE7構建的獨立服務器。

以下是連接到Datasnap服務器並請求數據時發生的事件的說明:

讓我進一步解釋一下:

通過使用一些ShowMessage指令,我可以在連接並發出數據請求時跟蹤Datasnap的流程。 在Test下運行服務器允許我顯示事件附帶的各種參數的內容。 設置完成后,運行連接到服務器並請求數據的客戶端會產生以下結果:

客戶登錄按鈕

  • 提交了憑證對話(這是我的代碼,而不是TSQLConnection的屬性,它錯了。)
  • 輸入用戶名和密碼。
  • Paremeters放置在TSQLConnection.Params [DSAuthenticationPassword,DSAuthenticationUser]中
  • 設置TSQLConnection.Connected:= True
  • 服務器事件OnUserAuthenticate

    此時,雖然服務器上沒有其他任何內容,但已建立連接。 最重要的是,ServerClass和ServerMethodsClass都沒有實例化。 我無法看到存儲身份驗證憑據的位置。

客戶端GetData按鈕

  • 客戶端連續打開兩個客戶端數據集。
  • 服務器DSServerClass1.Create。 這顯然意味着
    ServerTransport將請求識別為有效並繼續執行
    創建處理會話所需的資產。
  • ServerMethodsUnit3.Create。 隱藏在DSServerClass中的某處有一個GetClass調用,它返回相關ServerMethodsClass的名稱。 命名類被實例化。 由於ServerMethodsClass最終來自TDataModule,這也意味着屬性流。
  • OnUserAuthorize(顯然是第一個數據集)
  • OnUserAuthorize(顯然是第二個數據集)

數據返回給客戶端(此時,數據庫憑據被硬編碼到TFDConnection ConnectionDefinition中,只是為了讓它工作。)

OnUserAuthorize使用nil值顯示Sender參數; 還提供了一個TDSAuthorizeEventObject,它不包含我能夠用來查找ServerMethods實例的任何引用,最后還有一個名為Valid的參數,一個用於授權用戶的布爾值。

請注意,TDSAuthorizeEventObject包含對TDSServerMethodUserEventObject的引用,該引用包含用戶名以及角色,授權角色和拒絕角色。 但是,那又怎樣? 這讓我回到原來的問題: 如何將此信息傳達給ServerMethodsUnit中的代碼?

過了一段時間,我在Bob Swart的白皮書中偶然發現了確切的方法。 有幾種方法可以讓您在Datasnap會話期間保留信息。 它們屬於TDSSessionManager.GetThreadSession,分別是GetData,PutData,RemoveData,HasData,GetObject,PutObject,RemoveObject和HasObject。 這些方法實際上管理了作為Session一部分的兩個字典。 例如,在UserAuthentication事件中,您可以存儲用戶名,如下所示:

TDSSessionManager.GetThreadSession.PutData('entrykey', UserName);

稍后,在用於數據庫連接的OnBeforeConnect事件中,您可以檢索這些值以在連接中使用:

DBUserName := TDSessionManager.GetThreadSession.GetData('entrykey');

在實踐中,我發現“對象”形式具有更大的價值,但任何一種形式都提供了一種強大的方式,可以在不訴諸外部媒體的情況下在會話期間保留您自己的數據。

在鏈接的問題中TServerContainer1.DSAuthenticationManager1UserAuthenticate方法具有UserPassword參數。 您的服務器端代碼可以從請求參數中檢索憑據,驗證它們,然后重新使用它們進行數據庫身份驗證。

procedure TServerContainer1.DSAuthenticationManager1UserAuthenticate(
  Sender: TObject; const Protocol, Context, User, Password: string;
  var valid: Boolean; UserRoles: TStrings);

if UserService.isUserValid(User, Password) then
begin
  // use User and Password ... 

end; 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM