針對 SOAP Web 服務的 WS-Security 是相對的。通過在操作或消息級別配置 WS-Security,可以對所有交換應用適當程度的保護,減少或消除那些不需要完整保護的操作產生的 WS-Security 開銷。Dennis Sosnoski 將繼續他的 Java Web 訪問 系列,將通過 Apache Axis2 和 Rampart 探查 Web Services Description Language (WSDL) 中的細粒度 WS-Security。
在簡單 Web 服務環境中,客戶機直接連接到伺服器,而伺服器直接對請求執行所有必需的處理。正如本系列 上一篇文章 所述,使用 SSL 提供保護的連接可以為這類環境中的大部分應用提供出色的安全性。但是,更加複雜的環境變得越來越普遍,其中涉及到使用多層伺服器處理請求。在許多企業環境中日益流行的服務編排的完整理念就是以這種方法為基礎的,這與面向服務架構(SOA)的概念相同。在這些類型的環境中,必須實現更強大的 WS-Security 替代方案。
|
正如上一期文章所述,WS-Security 帶來了沉重的性能代價。降低成本的方法之一就是針對由服務定義的各個操作甚至是消息設置合適的 WS-SecurityPolicy,而不是將單個 WS-Security 策略應用到整個服務。WS-Security 的細粒度使用要求考慮更多的內容,而不是使用一成不變的方法,但是如果得到正確應用的話,那麼就可以減少常用操作的性能開銷,同時不會減弱需要 WS-Security 的操作的安全性。
定義策略
本文使用的樣例策略與 “Axis2 WS-Security 基礎” 和 “Axis2 WS-Security 簽名和加密” 中的策略相同 — 一個簡單的庫管理服務。(參見 下載 小節,獲得本文的完整源代碼)。這個服務定義了三種操作:
為了向安全用例中添加一些有趣的變化,本文作出以下假設:
在早期文章中,您已經了解了如何配置 Axis2/Rampart:將一個 WS-SecurityPolicy 文檔連接到 org.apache.axis2.client.ServiceClient 實例(在客戶機端),或者將策略文檔嵌入到 services.xml 服務配置(在伺服器端)。這個方法可以奏效,並且可用於測試,但是對於生產應用來說,最好通過將 WS-SecurityPolicy 內嵌到 WSDL 文檔將其直接關聯到服務定義。WS-Policy 和 WS-SecurityPolicy 旨在為這種嵌入提供支持,並且使用來自 <wsdl:binding>、<wsdl:binding>/<wsdl:operation> 或 <wsdl:binding>/<wsdl:operation>/<wsdl:message> 定義的引用標識將被應用到綁定、操作或消息的相應策略。Axis2 1.4.1 實現對內嵌在 WSDL 中的策略的初始處理,而這個實現在當前的 Axis2 1.5 發行版代碼中得到了改進。為了演示策略在 WSDL 中的使用,本文結合使用了 Axis2 1.5 發行版代碼和尚未發行的最新 Rampart 代碼(後者最終會作為 Rampart 1.5 發布)。
清單 1 展示了示例應用程序的 WSDL,其中添加了策略,並在相應的位置中引用。(清單 1 針對長度和寬度進行了編輯;完整的 WSDL 可以從 代碼下載 中的 library.wsdl 文件獲得)。每個策略定義了一個 Id 值,該值隨後從相應的操作(針對 UsernameToken 策略)或消息(針對簽名策略)中引用,以粗體顯示所有策略。
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl" xmlns:wns="http://ws.sosnoski.com/library/wsdl" xmlns:tns="http://ws.sosnoski.com/library/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"> <!-- Policy for signing message, with certificate from client included in each message to server --> <wsp:Policy wsu:Id="SignOnly" xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:AsymmetricBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:InitiatorToken> <wsp:Policy> <sp:X509Token sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/> </wsp:Policy> </sp:InitiatorToken> ... </wsp:Policy> </sp:AsymmetricBinding> <sp:SignedParts xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <sp:Body/> </sp:SignedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <!-- Policy for UsernameToken with plaintext password, sent from client to server only --> <wsp:Policy wsu:Id="UsernameToken" xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/> </wsp:Policy> </sp:SupportingTokens> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> ... <wsdl:binding name="LibrarySoapBinding" type="wns:Library"> <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getBook"> <wsdlsoap:operation soapAction="urn:getBook"/> <wsdl:input name="getBookRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="getBookResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="getBooksByType"> <wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#UsernameToken"/> <wsdlsoap:operation soapAction="urn:getBooksByType"/> <wsdl:input name="getBooksByTypeRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="getBooksByTypeResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="addBook"> <wsdlsoap:operation soapAction="urn:addBook"/> <wsdl:input name="addBookRequest"> <wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#SignOnly"/> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="addBookResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="library-granular"> ... </wsdl:service> </wsdl:definitions> |
清單 1 中的策略和 WSDL 均來自早期文章,不過沒有按照本文的方式事先合併。但是,您會發現策略中有一處顯著的不同:早期的版本都包括了 Rampart 配置信息,這些信息特定於客戶機或伺服器。現在策略被嵌入到 WSDL 中,因此不適合直接包含 Rampart 配置。(您需要編輯 WSDL 以包含客戶機 Rampart 配置信息,並在每次發生更改時重新生成代碼,而在伺服器端,Rampart 配置將被公開給訪問 WSDL 的任何人)。因此示例代碼將單獨設置配置信息。為此,對包含的 Rampart 配置使用了之前用於策略的相同技巧的不同變體。
客戶端使用
不管是否包含 WS-Policy,從用戶的角度來看,從 WSDL 中生成代碼的效果是相同的。如果查看由包含 WS-Policy 的 WSDL 生成的客戶機存根的內部,將發現策略在構建時被直接連接到服務描述的組件中,但是這被隱藏在實現的內部,不會影響到客戶機代碼使用的介面方法。
[火星人 ] Java Web 服務: WS-Security 的細粒度使用已經有519次圍觀