這次我們要真正的動手實作出一個可以將訊息進行加/解密的SOAP Extension功能。
前言
讓我們再複習一次Web Service生命周期示意圖 :
由上圖我們可以看出,一個由Client端送出的SOAP Request會經過以下流程:
1. Client端將資料序列化為XML後送出
2. Web Service端收到XML後將其反序列化回物件,並呼叫相對應的Web Method執行
3. Web Service將回傳值序列化為XML後送回給Client端
4. Client端收到Web Service回傳的XML後再將其反序列化回物件,進行後續動作
以前篇中的範例程式為例,當WPF Client端呼叫Web Service中的QueryMembersBySex方法取得性別為男生的資料時,會傳出的SOAP訊息內容如下:
很顯而易見的,只要有人有能力擷取到這段訊息或是Web Service端回傳的Response訊息,就可以不費吹灰之力的判讀出內容的涵意,或是仿造出相同格式的訊息。
如此一來,就算不公佈WSDL,也是有可能被其他第三方有心人士得知系統中提供的各個WebMethod所提供的訊息介面。
如果我們不想改變WSDL的結構,但是又想保護在網路中傳遞的訊息的話,我們可以在以下幾個階段改寫SOAP訊息的內容,將SOAP訊息加以加密,並以統一的格式收送:
如此就可以達到我們的目的。
而要在上述的幾個時機點對SOAP訊息動手腳這個重責大任,就透過SOAP Extension來完成了。
動手實作
接下來,我們要透過一個簡單的小範例,來說明怎麼實作出一個「只能接受自訂SOAP格式的Web Service與Client端」。
為了簡化開發的流程,我在方案中另外建立了一個Class Libray專用,以提供加密後的SOAP Message內容型別、加/解密功能以及最重要的SOAP Extension供Web Service與Client端共用。
在開始動手寫Code之前,請先將System.Web.Services加入專案的參考,以供SOAP Extension使用。
接著要在專案中加入以下幾個類別:
1. MySoapMessage – 用來定義SOAP訊息中訊息的格式(這邊為了簡化,整個類別中就只放一個字串,用來存放加密過的訊息)。
2. Encryptor – 用來處理訊息的加/解密功能(很基本的以AES演算法進行加解密的類別,不多作解釋)。
3. MyEncryptionExtension – SOAP Extesnion本體。
4. MyEncryptionExtensionAttribute – 與SOAP Extension搭配的屬性(若同時有多個SoapExtension要掛在同一個WebService中,也可以透過這個屬性來決定執行的先後順序)。
完成以上的工作之後,再來就可以將Soap Extension分別掛載進Web Service端與WPF Client端了,在進行接下來的動作之前,請務必先確認Web Service專案與WPF Client專案都已加入MySimpleMessageUtility專案的參考。
將Web Service的Web Method加上Soap Extension的方法非常簡單,只需要在Web Method上加上要掛載的Soap Extesnion Attribute即可,範例如下:
而Client端要掛上Soap Extension更簡單,只要在app.config/web.config裡的system.web區段中加入以下設定就行了:
還有很重要的一點,既然說我們是要透過AES演算法對訊息的內容進行加/解密,那麼WebService和Client端裡加/解密所需要使用到的Key和IV就不能漏掉啦!!這邊就在兩個專案的config檔的appSettings區段中分別加入以下設定:
這些步驟都完成之後,就可以試著執行專案,看看是不是可以正常的運作囉!!~
若以除錯模式針對WPF Client端送出的訊息,會發現送出的訊息變成如下的格式,且還是可以從Web Service端取回資料喔!!
額外小叮嚀:
透過本文所介紹的方式,就可以做到某種程度的資料保護效果,只要Client端沒有實作一樣的Soap Extension來傳送資料,那Web Service端可是不會買帳的喔!!(也就是說,WSDL中提供的訊息介面就變成參考用,如果直接呼叫可是會碰壁的啊~~)
而除了針對訊息進行加/解密之外,也可以透過Soap Extension來進行對訊息的壓縮或是記錄等等工作,有興趣的朋友們不妨研究看看喔!!
本文專案原始碼如下,請自行取用: