 |
 |
內(nèi)容: |
 |
|
 |
相關(guān)內(nèi)容: |
 |
|
 |
訂閱: |
 |
|
|
柴曉路 Chief System Architect 2001 年 10 月
本文應(yīng)SOAP/1.2規(guī)范推出的技術(shù)背景,就運(yùn)用SOAP Header擴(kuò)展SOAP的功能展開討論。當(dāng)具體的應(yīng)用中運(yùn)用了一些與應(yīng)用本身關(guān)聯(lián)不是太大而更面向底層控制的服務(wù)的時候應(yīng)當(dāng)采用SOAP Header來傳輸這些控制信息,理由是這些服務(wù)往往是平臺的功能而非具體應(yīng)用所要實(shí)現(xiàn)的功能。從體系架構(gòu)的觀點(diǎn)來看,解析SOAP Header的就可以由平臺模塊來完成,通過插入不同的標(biāo)準(zhǔn)化的SOAP Header條目解析模塊來完成不同目的的控制功能。而相應(yīng)的,解析SOAP Body是由應(yīng)用模塊來完成。這樣在開發(fā)和部署上將會非常地清晰。
W3C XML Protocol工作組在今年7月發(fā)布了SOAP Version 1.2 Working Draft (SOAP規(guī)范1.2版草案,網(wǎng)址是" http://www.w3.org/TR/2001/WD-soap12-20010709/")。同時在2001年4月,在美國的San Jose召開的Web服務(wù)研討會上正式確立了SOAP作為Web服務(wù)的核心規(guī)范的地位。
在SOAP/1.2版中,對于如何拓展SOAP的能力作了明確的指示性的描述,那就是SOAP Body關(guān)注于調(diào)用本身(基本沒有變化),而SOAP Header從先前的可以由SOAP中介結(jié)點(diǎn)處理的模糊指示轉(zhuǎn)變?yōu)镾OAP Header是擴(kuò)展SOAP功能的最佳途徑的明確性指示。
我們知道,SOAP的應(yīng)用已經(jīng)有了一定的階段,各種基于SOAP調(diào)用的Web服務(wù)紛紛出現(xiàn)。然而,目前的應(yīng)用模式基本上停留在遠(yuǎn)程過程/對象的調(diào)用上,基于多次協(xié)調(diào)調(diào)用或者遵循上下文的調(diào)用模式尚很少使用,這其實(shí)是受簡單的SOAP消息的制約。如果擴(kuò)展,而且是遵循標(biāo)準(zhǔn)的擴(kuò)展SOAP消息以滿足更復(fù)雜情況下的應(yīng)用成為了目前的一個發(fā)展趨勢。
更新的SOAP概念
在討論運(yùn)用SOAP Header來擴(kuò)展SOAP功能之前,我們先來看看SOAP/1.2中更新的一些SOAP的基本概念,這些是理解后面的內(nèi)容的基礎(chǔ)。
SOAP結(jié)點(diǎn) (SOAP Node)
SOAP結(jié)點(diǎn)根據(jù)SOAP定義的整套規(guī)范來處理SOAP消息。SOAP結(jié)點(diǎn)有責(zé)任遵守SOAP消息交換的規(guī)則以及提供通過依賴底層協(xié)議的SOAP綁定來訪問的服務(wù)。任何不符合SOAP約定的情況都將導(dǎo)致SOAP結(jié)點(diǎn)產(chǎn)生一個SOAP fault(SOAP錯誤)。
SOAP條目 (SOAP Block)
SOAP條目是一個句法上的結(jié)構(gòu),它用于包含一個邏輯上的單一元素,這一元素是需要被SOAP結(jié)點(diǎn)處理的。一個SOAP條目是由該條目最外層元素的完整修飾名(帶命名空間修飾)所標(biāo)識的,這個完整修飾名是由一個局部名和一個命名空間URI組成的。封裝在SOAP Header中的SOAP條目稱為Header條目,而封裝在SOAP body中的SOAP條目為Body條目。
SOAP Header (SOAP頭)
能夠被SOAP消息傳輸路徑中任意的SOAP接受者結(jié)點(diǎn)處理的一組SOAP條目(0個或多個)。
SOAP Body (SOAP體)
能夠被SOAP消息路徑中的最終SOAP接受結(jié)點(diǎn)處理的一組SOAP條目(0個或多個)。
SOAP發(fā)送者
SOAP發(fā)送者是發(fā)出SOAP消息的SOAP結(jié)點(diǎn)。
SOAP接收者
SOAP接收者是接受SOAP消息的SOAP結(jié)點(diǎn)。
SOAP消息路徑
為傳送一個簡單的SOAP消息而要經(jīng)過的一組SOAP發(fā)送者和SOAP接受者。其中包含了初始SOAP發(fā)送者、零個或多個SOAP中介結(jié)點(diǎn)以及最終的SOAP接受者。
初始SOAP發(fā)送者
SOAP消息的最初產(chǎn)生者,同時也是SOAP消息路徑的第一個結(jié)點(diǎn)。
SOAP中介結(jié)點(diǎn)
SOAP中介結(jié)點(diǎn)即是SOAP接收者也是SOAP發(fā)送者,是SOAP消息可到達(dá)的某一個應(yīng)用程序。當(dāng)SOAP消息沿著SOAP消息路徑傳輸時,SOAP中介結(jié)點(diǎn)將處理一組確定的SOAP條目,然后它將消息轉(zhuǎn)發(fā)給消息路徑的下一個SOAP結(jié)點(diǎn),直至傳送到最終SOAP接收者。
最終SOAP接收者
由初始SOAP發(fā)送者指定的通過SOAP消息路徑傳送的SOAP消息的最終的接收者。如果在SOAP消息路徑中有SOAP結(jié)點(diǎn)產(chǎn)生了SOAP錯誤,那么SOAP消息將不會到達(dá)最終接收者。
同時SOAP/1.2使用了新的命名空間,命名空間前綴"env"和"enc"等關(guān)聯(lián)的SOAP/1.2命名空間分別位于:"http://www.w3.org/2001/06/soap-envelope"和"http://www.w3.org/2001/06/soap-encoding"。
SOAP角色與SOAP Header處理模式
當(dāng)SOAP結(jié)點(diǎn)接受并處理一個SOAP消息的時候,該SOAP結(jié)點(diǎn)將被告知應(yīng)當(dāng)以一個或多個SOAP處理角色來處理,這些SOAP角色是由SOAP角色名來標(biāo)識,SOAP角色名的具體表示是使用一個env:actor屬性來表示,其值是一個URI。
每個SOAP結(jié)點(diǎn)都必須以一個指定的角色來處理,也就是說任意一個SOAP結(jié)點(diǎn)都屬于這個角色,這個角色使用命名為"http://www.w3.org/2001/06/soap-envelope/actor/next"的SOAP角色來表示,同時可以按照需要應(yīng)用零個或多個其他的SOAP額外角色,當(dāng)然這些角色應(yīng)當(dāng)使用不同與前面介紹的這個SOAP角色名。
SOAP結(jié)點(diǎn)可以通過以匿名SOAP角色來實(shí)施處理以使得自己成為最終SOAP接收者。當(dāng)SOAP結(jié)點(diǎn)在處理一個SOAP消息的時候,其表現(xiàn)出的SOAP角色在整個處理過程中不得更改。這是因?yàn)镾OAP規(guī)范只涉及如何處理單個SOAP消息而無需考慮狀態(tài)(這也是SOAP設(shè)計(jì)目標(biāo)之一的簡明性的體現(xiàn)),因此是否允許在處理單個SOAP消息的時候轉(zhuǎn)換角色是沒有意義的。
從本質(zhì)上說,SOAP角色名是用來識別SOAP結(jié)點(diǎn)的,通常使用某種URI的形式,SOAP的角色名并沒有與路由或者消息交換的語義相聯(lián)系。舉例來說,一個SOAP角色可以被命名為一個用于在發(fā)送SOAP消息給適當(dāng)SOAP結(jié)點(diǎn)中表示接收結(jié)點(diǎn)訪問入口的URI。相反,也有這樣一些SOAP角色的名字,這些名字或者直接和消息路由相聯(lián)系(例如,"http://example.org/banking/anyAccountMgr"),或者和路由沒有聯(lián)系(例如,當(dāng)一個消息頭被用來攜帶這樣一種指示性的信息,該指示信息用于告知任何相關(guān)的SOAP消息的接受應(yīng)用軟件,這個SOAP消息是長期不變的,因此是能夠被安全的緩存和重用的,在這種SOAP消息頭中,可以利用一個標(biāo)識"所有緩存管理軟件"的URI來指明SOAP角色),通過名字使用這些SOAP角色也是合適的。
總而言之,SOAP角色的名并沒有預(yù)定義為一定要與某種語義相關(guān)聯(lián),用戶可以使用某種語義關(guān)聯(lián)的URI來表示,也完全可以用類似UUID這樣的沒有語義的URI來表示,這完全要看具體的應(yīng)用的需要。
SOAP Header條目包含可選的env:actor屬性,用來把他們定位到合適的SOAP結(jié)點(diǎn)。沒有該屬性的SOAP Header隱含地被定位到一個匿名的SOAP角色,這意味著他們將被最終SOAP接收者所處理。我們把SOAP actor屬性的值(隱含的或者直接指明的)作為相應(yīng)SOAP條目(SOAP Header條目或者SOAP Body條目)的SOAP角色。
如果是:
- SOAP條目中SOAP actor屬性的值(如果出現(xiàn)的話)匹配了一個SOAP結(jié)點(diǎn)的角色;
- 或者是當(dāng)SOAP條目沒有actor屬性(不僅對于SOAP Header條目有效,也同時包括SOAP Body條目,值得注意的是在SOAP/1.1中,actor屬性只能應(yīng)用于SOAP Header條目),而該SOAP結(jié)點(diǎn)已經(jīng)被假設(shè)為匿名SOAP角色。
這時我們就說SOAP條目被指向一個SOAP結(jié)點(diǎn),同時將被該SOAP結(jié)點(diǎn)處理。
Figure 1. SOAP Header條目的標(biāo)準(zhǔn)化處理模式
我們認(rèn)為隨著時間的過去,會有大量的SOAP Header函數(shù)規(guī)范出現(xiàn),而且每個SOAP結(jié)點(diǎn)都可以包含一個或多個處理這些擴(kuò)展所必須的軟件。如果SOAP結(jié)點(diǎn)的應(yīng)用軟件是完全兼容而且實(shí)現(xiàn)了那些由條目中完整修飾的最外層元素名所傳遞的語義,我們說這個SOAP Header被一個SOAP結(jié)點(diǎn)理解。
在Figure 1中,以形象化的形式描述了這種將來可能的依據(jù)某種Header函數(shù)規(guī)范的標(biāo)準(zhǔn)化處理方式。其實(shí)質(zhì)就是在SOAP的框架下,定義了一整套SOAP Header條目的語義集及其處理規(guī)范。例如,將來可能會出現(xiàn)一組專用于訪問控制的SOAP Header條目集。其中可能包含這樣兩種SOAP Header條目:(假定他們的命名空間為xmlns:auth="soap:header: authentication")
- 用戶認(rèn)證:auth:get_authToken,在這個SOAP Header條目下,包含兩個子元素userID和password,用于完成用戶認(rèn)證操作并獲取認(rèn)證令牌;
- 訪問授權(quán):auth:judge_accessList,在這個SOAP Header條目下,包含一系列的子元素accessResource,每個accessResource有兩個屬性authToken和resourceURI,分別用于表示提供的認(rèn)證令牌和待訪問的資源URI,這個SOAP Header條目用于判定這些資源是否授權(quán)于給定的人證令牌以訪問權(quán)限,如果是,那么授予了什么樣的權(quán)限。
如果這樣一種SOAP Header條目的規(guī)范被投入實(shí)用后,任何SOAP結(jié)點(diǎn)只需要部署了兼容該規(guī)范的SOAP處理程序,就能夠處理這樣的SOAP Header條目。
對于SOAP結(jié)點(diǎn)而言,除env:actor屬性之外,尚有另一個重要的屬性:env:mustUnderstand。當(dāng)定位到一個SOAP結(jié)點(diǎn)的SOAP Header條目的env:mustUnderstand屬性為"1",被指向的SOAP結(jié)點(diǎn)必須:
- 或者依照由條目中完整修飾的最外層元素名傳遞的語義來處理SOAP塊;
- 或者更本不處理SOAP消息而失敗。
也就是說,不可以在任何情況下忽略對這種SOAP Header條目的處理。
SOAP功能擴(kuò)展: 權(quán)限認(rèn)證
在以下的篇幅,將結(jié)合具體的應(yīng)用實(shí)例來詳細(xì)地闡述SOAP Header條目的意義以及SOAP Header屬性的作用,同時期望大家能夠了解到從設(shè)計(jì)者的角度,是如何對SOAP進(jìn)行體系架構(gòu)的。
第一個例子是利用SOAP Header條目進(jìn)行權(quán)限認(rèn)證:
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<auth:authentication xmlns:auth="http://example.org/authentication "
env:actor="authentication:signin_service"
env:mustUnderstand="1">
<auth:userID>testuserid</auth:userID>
<auth:password>[encodedPassword]</auth:password>
<auth:redirection>http://example.com/service/</auth:redirection>
</auth:authentication>
</env:Header>
|
在這個例子中,SOAP Header條目authentication被交付給專門的權(quán)限認(rèn)證Web服務(wù)進(jìn)行用戶認(rèn)證(該服務(wù)使用角色名"authentication:signin_service"來標(biāo)識),該Web服務(wù)通過檢查authentication條目中包含的用戶名(userID)和密碼(password)來確認(rèn)該用戶是否能通過認(rèn)證檢查。如果無法通過認(rèn)證檢查,將返回調(diào)用者一個SOAP錯誤,如果能夠通過認(rèn)證檢查,則該認(rèn)證Web服務(wù)在該Header條目中刪除userID和password,然后插入一個新的元素authInfo,這是一個認(rèn)證令牌,可用于以后在需授權(quán)服務(wù)調(diào)用中使用。接著,該Web服務(wù)將這條消息傳遞給由redirection元素指定的地址的Web服務(wù),這個Web服務(wù)可以通過校驗(yàn)認(rèn)證令牌以審核該次調(diào)用。
從認(rèn)證Web服務(wù)發(fā)送到后續(xù)Web服務(wù)的SOAP消息中的Header片斷的可能內(nèi)容可參見下面的代碼段:
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<auth:authentication xmlns:auth="http://example.org/authentication "
env:mustUnderstand="1" >
<auth:authInfo>[encodedAuthInfo]</auth:authInfo>
</auth:authentication>
</env:Header>
|
大家可以發(fā)現(xiàn)在這個后續(xù)的SOAP消息中,authentication條目中的redirection元素也已經(jīng)被刪除了(也就是已經(jīng)被使用了,作為新的SOAP結(jié)點(diǎn)的地址)。
SOAP功能擴(kuò)展: 事務(wù)控制
第二個例子是利用SOAP Header條目進(jìn)行事務(wù)控制。這個應(yīng)用背景是這樣的,在一個商務(wù)事務(wù)處理應(yīng)用環(huán)境中,由Web服務(wù)A發(fā)起事務(wù),一個事務(wù)會包含多個操作,而這些操作可能要經(jīng)過其他的一些Web服務(wù)進(jìn)行計(jì)算后才能生成,而所有的操作將會被發(fā)往Web服務(wù)Z,由Web服務(wù)Z完成整個事務(wù)。整個事務(wù)的執(zhí)行模式可參見下圖。
Figure 2. 事務(wù)控制模型
其中的消息序列將是這樣:
- Web服務(wù)A向Web服務(wù)Z發(fā)出事務(wù)啟動的總控消息;
- Web服務(wù)A向Web服務(wù)G、H、I發(fā)出操作生成請求消息;
- Web服務(wù)G、H、I分別向Web服務(wù)Z發(fā)出事務(wù)中的具體操作的描述消息,以最終完成整個事務(wù)。
也就是說Web服務(wù)A是事務(wù)的控制點(diǎn),Web服務(wù)Z是事務(wù)的提交點(diǎn),而Web服務(wù)G、H、I則分別是事務(wù)的產(chǎn)生點(diǎn)。
總控消息的Header片斷的內(nèi)容為:
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<transaction:transaction
xmlns:transaction="http://example.org/transaction"
env:actor="transaction:submission_point">
env:mustUnderstand="1">
<transaction:transactionKey>8259bd00-2f9c-4493-a09f-414e3a4559a6
</transaction:transactionKey>
<transaction:operations>
<transaction:count>3</transaction:count>
</transaction:operations >
</transaction:Transaction>
</env:Header>
|
在這條消息中,有一個SOAP Header條目transaction,它的子元素transactionKey表示了啟動的事務(wù)的鍵值。而另一個子元素operations則包含了一個描述該事務(wù)包含的所有操作的數(shù)量的子元素count。當(dāng)Web服務(wù)Z接受到這條消息后,將為該事務(wù)啟動一個消息池,該消息池的標(biāo)識為transactionKey的值。
然后Web服務(wù)A向Web服務(wù)G、H、I發(fā)出事務(wù)啟動消息,通知這些服務(wù)指定事務(wù)可以開始提交操作了。
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<transaction:transaction
xmlns:transaction="http://example.org/transaction"
env:actor="transaction:operation_point" >
env:mustUnderstand="1">
<transaction:transactionKey>8259bd00-2f9c-4493-a09f-414e3a4559a6
</transaction:transactionKey>
<transaction:action>start</transaction:action>
</transaction:Transaction>
</env:Header>
|
當(dāng)Web服務(wù)G、H、I分別向Web服務(wù)Z發(fā)出操作消息(參見圖 4 25)時,Web服務(wù)Z分別將這些收到的消息放入指定的消息池中,當(dāng)消息池中的操作消息的數(shù)量達(dá)到count元素中指定的數(shù)量后,Web服務(wù)Z將關(guān)閉該消息池,按照次序,執(zhí)行該事務(wù),待執(zhí)行完畢后,向Web服務(wù)A發(fā)送一個通知消息。
<env:Header xmlns:env="http://www.w3.org/2001/06/soap-envelope" >
<transaction:transaction
xmlns:transaction="http://example.org/transaction"
env:actor="transaction:submission_point" >
env:mustUnderstand="1">
<transaction:transactionKey>8259bd00-2f9c-4493-a09f-414e3a4559a6
</transaction:transactionKey>
<transaction:operations>
<transaction:serialNo>1</transaction:serialNo>
</transaction:operations >
</transaction:Transaction>
</env:Header>
|
小結(jié)
在本文中按照SOAP規(guī)范的約定,給出了兩個運(yùn)用SOAP Header條目對SOAP的能力進(jìn)行擴(kuò)充的例子。我們認(rèn)為,當(dāng)具體的應(yīng)用中運(yùn)用了一些與應(yīng)用本身關(guān)聯(lián)不是太大而更面向底層控制的服務(wù)的時候應(yīng)當(dāng)采用SOAP Header來傳輸這些控制信息,理由是這些服務(wù)往往是平臺的功能而非具體應(yīng)用所要實(shí)現(xiàn)的功能。按照規(guī)范的約定,SOAP Body是專用于交換調(diào)用的具體信息,而控制信息的交互應(yīng)當(dāng)由SOAP Header來完成。
這樣,從體系架構(gòu)的觀點(diǎn)來看,解析SOAP Header的就可以由平臺模塊來完成,通過插入不同的標(biāo)準(zhǔn)化的SOAP Header條目解析模塊來完成不同目的的控制功能。而相應(yīng)的,解析SOAP Body是由應(yīng)用模塊來完成。這樣在開發(fā)和部署上將會非常地清晰。
隨著SOAP Header擴(kuò)展的普遍應(yīng)用和標(biāo)準(zhǔn)的形成,將意味著SOAP技術(shù)的真正成熟。 |