單層服務架構下 SSL 足矣,但現代 SOA/服務編排常涉多層服務鏈,需更強大的 WS-Security。然而 WS-Security 帶來巨大性能開銷。解決之道:針對各操作/訊息施以恰當策略,而非整個服務套用單一策略。本文演示如何在 WSDL 中內嵌 WS-SecurityPolicy 實現操作級、訊息級細粒度安全控制,並以 Axis2/Rampart 為例說明客戶端與服務端配置。
getBook:公開查詢,**無安全性**。getBooksByType:需授權,**UsernameToken** 驗證。addBook:需審計追蹤,**簽名**請求訊息 (非回應)。WS-Policy/WS-SecurityPolicy 設計支援將策略內嵌 WSDL,通過 wsu:Id 標識,在 <wsdl:binding>、<wsdl:operation>、<wsdl:message> 通過 <wsp:PolicyReference URI="#Id"/> 引用。
清單 1 關鍵片段:
<wsp:Policy wsu:Id="SignOnly"> ... <sp:AsymmetricBinding>...<sp:SignedParts><sp:Body/></...> </wsp:Policy>
<wsp:Policy wsu:Id="UsernameToken"> ... <sp:SupportingTokens><sp:UsernameToken/></...> </wsp:Policy>
<wsdl:binding name="LibrarySoapBinding" type="wns:Library">
<wsdl:operation name="getBook"> ... </wsdl:operation> <!-- 無策略引用 -->
<wsdl:operation name="getBooksByType">
<wsp:PolicyReference URI="#UsernameToken"/> <!-- 操作級引用 -->
...
</wsdl:operation>
<wsdl:operation name="addBook">
<wsdl:input name="addBookRequest">
<wsp:PolicyReference URI="#SignOnly"/> <!-- 訊息級引用 (僅輸入) -->
</wsdl:input>
...
</wsdl:operation>
</wsdl:binding>
策略與 Rampart 配置分離:WSDL 僅含安全意圖,Rampart 具體配置 (Keystore、CallbackHandler 等) 另存獨立策略文件,客戶端/服務端分別應用。
ServiceClient 應用 Rampart 配置策略並啟用模組:
LibraryGranularStub stub = new LibraryGranularStub(target);
ServiceClient client = stub._getServiceClient();
client.getAxisService().applyPolicy(loadPolicy("rampart-client-policy.xml"));
client.engageModule("rampart");
Options opts = client.getOptions();
opts.setUserName("libuser");
opts.setPassword("books");
Rampart 客戶端配置策略包含簽名用 Keystore、密碼回調類等。
將 Rampart 配置策略合併至 services.xml 對應操作定義中 (而非整個服務)。使用 PolicyTool 程序自動合併。
合併後 services.xml 關鍵結構:
<service name="library-granular">
<operation name="getBook"> ... </operation> <!-- 無 Rampart -->
<operation name="getBooksByType">
<module ref="rampart"/>
<wsp:Policy> ... Rampart 配置 ... </wsp:Policy>
</operation>
<operation name="addBook">
<module ref="rampart"/>
<wsp:Policy> ... Rampart 配置 ... </wsp:Policy>
</operation>
</service>
部署 AAR 後,管理控制台可見僅兩操作掛載 Rampart 模組。運行驗證:
getBook:無 WS-Security Header。getBooksByType:請求含 UsernameToken Header。addBook:請求 (非回應) 含簽名 Header。<wsp:ExactlyOne> 中除第一個外的所有選項。將 WS-SecurityPolicy 內嵌 WSDL 並按操作/訊息引用,是實現細粒度安全的標準路徑。Axis2/Rampart 提供了初步支援,足以覆蓋常見用例,但企業級生產環境需評估其限制。後續文章將探討其他框架 (如 Metro/CXF) 的 WS-Security 實現與性能表現。