WebService通過TSoapHeader驗證

WebService使得不同開發工具開發出來的程序可以在網絡連通的環境下相互通信,它最大的特點就是標準化(基於XML的一系列標準)帶來的跨平臺、跨開發工具的通用性,基於HTTP帶來的暢通無阻的能力(跨越防火牆)。
WebService給我們的軟件開發帶來了諸多好處,但是有一點還是必須要考慮到的,那就是安全問題。提供Service的一方要控制用戶的限制訪問,就要對來訪的用戶進行身份驗證。驗證成功則繼續提供服務,否則就觸發無權訪問的異常,返回給客戶。那麼現在我們要解決的問題是這樣的:用戶的身份認證信息如何在調用主要服務前發送到服務方,從而進行驗證?
在WebService中,用戶身份認證信息可以在客戶端通過soap頭(soap header)進行傳送。在WebService服務端的編寫中,需要對soap頭進行處理,這個處理過程就是提取Soap Header中的用戶認證信息進行驗證。下面就來看看在Delphi中這個身份認證是如何實現的。

一、   自定義的Header類
你需要定義一個用來存放認證信息的類,這個類繼承於TSoapHeader。
TAuthHeader = class(TSOAPHeader)
private
FUserName: WideString;
FPassWord: WideString;
published
property UserName: WideString read FUserName write FUserName;
property PassWord: WideString read FPassWord write FPassWord;
end;
這個類包含了用戶名和密碼兩個屬性,當然你可以根據情況增加更多的信息。
再說一下這個類是在哪定義的,它是定義在服務端的接口聲明單元。服務發佈以後,生成的WSDL中會有這個類的定義,這樣在客戶端用WSDL Importer導入接口單元的時候,這個類也會自動生成,當然你還要在服務端對這個類進行註冊:
InvRegistry.RegisterHeaderClass(TypeInfo(ISoapAuth), TAuthHeader);
RemClassRegistry.RegisterXSClass(TAuthHeader);
ISoapAuth是服務端提供的服務接口。

二、   客戶端發送Header
我們還假設ISoapAuth是服務端提供的服務接口,它提供了GetInfo()這麼一個服務。
客戶端程序片段:
procedure TClientForm.GetInfoButtonClick(Sender: TObject);
var
aIntf: ISoapAuth;
Headers: ISOAPHeaders;
H: TAuthHeader;
Begin
aIntf := (HTTPRio as ISoapAuth);
H := TAuthHeader.Create;
H.UserName := ‘piao’ ; //這裏只是舉個例子
H.PassWord := ‘840717’; 
Try
Headers := (aIntf as ISOAPHeaders);
Headers.Send(H); //發送Soap Header
aIntf.GetInfo; //調用服務
finally
aIntf := nil;
H.Free;
End;
end;
客戶端的工作就是這些了,能否調用服務還要看服務端的處理結果了。

三、   服務端接收處理Header
服務端程序片段:
function TSoapAuth.GetServerInfo: WideString;
var
Headers: ISoapHeaders;
H: TAuthHeader;
begin
Headers := Self as ISoapHeaders;
Headers.Get(TAuthHeader, TSoapHeader(H)); //先獲取SoapHeader
try
    if H = nil then //SoapHeader 爲空
      raise ERemotableException.Create('No authentication header')
    else
      if not CheckUser(H.UserName, H.PassWord) then   //驗證失敗
        raise ERemotableException.Create('No acess to call on service!');
finally
    H.Free;
end;
Result := 'Hello World!';
end;
以上,TSoapAuth是繼承於TInvokableClass 實現 ISoapAuth 的類。
CheckUser()是用來驗證用戶是否具有訪問權限的函數,在服務端定義。
這只是個簡單的返回字符串的服務。


四、   對訪問WebService的用戶的狀態的探討
事實上客戶端在每次調用服務端的服務接口時會重新生成一個對象,發送請求,然後接收返回結果,整個調用過程結束後這個對象就被釋放。所以可以說WebService是個無狀態的對象,也就不存在用戶是否登陸的說法。這樣的結果使得我們每次調用服務時就必須做一次用戶認證(這個認證可能是查詢數據庫比對),是比較浪費時間和資源的。
如果一定要在服務端保存用戶的登陸狀態,那麼可以在服務端加一個LogIn()的函數。當用戶第一次訪問服務時,調用LogIn()記錄下用戶的狀態信息,並且賦給這個用戶在一段時間內無限制(是指不必經過CheckUser這個過程)訪問服務的權限,當這段時間過後,用戶的登陸狀態被釋放掉,必須重新登陸才能繼續調用服務。
至於這個用戶狀態信息如何在服務端保存,就可能有幾種方法了。一是用文件形式保存(xml或ini),二是數據庫保存,三是用程序中的變量保存(可以在程序中定義一個UserList的變量來記錄用戶的狀態信息)。
發佈了6 篇原創文章 · 獲贊 12 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章