使用策略集構建符合 WS-security 安全規範的 JAX-WS Web Service 客戶端

CloudSpace發表於2008-09-10

JAX-WS 的 Web Service 可以通過滿足 WS-Security 規範來提供安全的 Web Service,但是也需要滿足 WS-Security 的 Web Service 客戶端才能呼叫。本文結合 WebSphere 裡的開發工具 AST(Application Server Toolkit) 介紹了使用 WebSphere 策略集開發滿足 WS-Security 的 standalone 的 Web Service 客戶端,使其在不依賴於 WAS 的 J2EE 容器環境下也能呼叫安全的 Web Service。

引言

WebSphere Application Server 6.1(WAS6.1)的 Web Service Feature Pack 提供了對 JAX-WS 2.0 這種新的 Web Service 標準的支援。同時,通過策略集(Policy Set)的方式,來滿足 Web Service 的服務質量(QoS)。其中,WS-Security 規範使用了訊息加密和數字簽名的方法來保證 SOAP 訊息在傳送中的安全性和完整性。Web Service 客戶端在呼叫使用了 WS-Security 的 Web Service 的時候,自身也必須滿足 WS-Security 的規範。如果客戶端是使用 WebSphere Application Server 6.1(加上 Web Service Feature Pack)作為容器的 J2EE 應用,我們可以通過和伺服器端同樣的方式來配置 WS-Security 所要使用的證照和金鑰。但是並不是所有的 Web Service 客戶端都是 J2EE 專案,並且使用 WAS6.1 作為伺服器。在一個典型的中小客戶和大型企業使用 Web Service 進行 B2B 對接的場景中,中小型客戶需要使用手中僅有的 standalone 的 java 程式作為客戶端,來呼叫大型企業安全的 Web Service。對於這種 standalone 的 java 客戶端,需要一種簡單可行的方式來滿足 WS-Security。WAS 的開發工具 AST(Application Server Toolkit)6.1.1.3 以及 Rational Application Developer 7.0(需要安裝 Web Service Feature Pack)中加入了這樣的功能,通過與伺服器端類似的策略集配置使得客戶端也能保證 Web Service 的 QoS,其中包含 WS-Security。

本文通過一個例子來構建滿足 WS-Security 的 Web Service 客戶端,並且這個客戶端不依賴於任何伺服器或 Web 容器,執行在 J2SE 單機環境中。本文首先給出了一個 Web Service 示例服務的 WSDL,描述一個 Web Service 的伺服器提供的一個 Web 服務,接下來詳細介紹使用 AST 構建這個安全的 standalone 的 Web Service 客戶端的步驟,最後說明詳細的測試方法,包括使用 TCP/IP 監視器來監控測試報文。

術語說明

  • WAS6.1 本文特指安裝了 Web Service Feature Pack 的 WebSphere Application Server 6.1;
  • 客戶端本文特指不依賴任何應用伺服器或 Web 容器的 Web Service 消費者,執行在 J2SE 單機環境中

WSDL

Web Service 客戶端通過服務端的 Web 服務描述語言(WSDL)來獲取 Web Service 提供者的介面資訊,並且使用這個描述語言來構建客戶端的檔案。本文使用瞭如下的 WSDL 來描述伺服器端的介面。


清單 1. WSDL

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

此服務描述語言描述了伺服器端提供了一個回聲的 Web Service,它有一個字串格式的輸入引數,返回值也是一個字串格式的引數。Web Service 的服務地址為 http://localhost:9095/EchoWeb/Echo。

構建過程

在得到 Web Service 的介面描述 WSDL 之後,我們就可以開始構建我們的安全的 Web Service 客戶端了。本文按照以下的構建步驟來描述整個的客戶端的開發過程:

  1. 構建所需的 Java 檔案:通過 WSDL 生成開發客戶端所需的 Java 類;
  2. 編寫客戶端實現程式碼:開發 Web Service 客戶端的呼叫邏輯;
  3. 準備客戶端金鑰庫檔案:為 WS-Security 所需的簽名加密等動作準備金鑰;
  4. 配置客戶端 WS-Security 策略集:使得 Web Service 客戶端滿足 WS-Security 的規範。

構建所需的 Java 檔案

wsimport 工具用來從 WSDL 建立 Web Service 所需要的 Java 類檔案,包括 JAXB 輔助類和 service 代理類,此工具可以在 \AppServer\bin 下找到。


清單 2. 使用 wsimport 生成 Web Service 所需類檔案
wsimport –keep –verbose –p ws.client.echo –wsdllocation file:/c:/wsclient/Echo.wsdl \
Echo.wsdl

主要選項說明:

  • -keep 保留生成的 Java 原始檔,否則只有 class 位元組碼檔案;
  • -verbose 在命令列顯示生成的 Java 原始檔;
  • -p 指定生成的 Java 包選項,即原始檔的 import 值,並按照選項後面的引數生成目錄結構,將生成檔案置於此目錄中;
  • -wsdllocation 用來指定使用的 WSDL 的具體位置,這個值會寫在生成的 Service 實現類裡,Service 實現類將從這個位置來獲取 WSDL;

生成的類檔案:

  • ws\client\echo\Echo.java Web Service 端點介面(Service Endpoint Interface,簡稱 SEI),包含服務方法簽名;
  • ws\client\echo\Echo_Service.java JAXWS 生成的 javax.xml.ws.Service 的實現,包含 WSDL 資訊,用來生成 SEI 實現
  • ws\client\echo\EchoHello.java JAXB 物件,對應 SOAP 訊息中的 EchoHello 元素;
  • ws\client\echo\ObjectFactory.java 建立 EchoHello 和 RequestEcho 的工廠類;
  • ws\client\echo\package-info.java 包含名稱空間和包資訊;
  • ws\client\echo\RequestEcho.java JAXB 物件,對應 SOAP 訊息中的 RequestEcho 元素。

編寫客戶端實現

開啟 AST6.1.1.3 的一個工作空間,建立一個 Java 專案:EchoClientStandalone,將前面生成的檔案拷貝至 ws.client.echo 包中。

在這個包中建立類 Echo_Client 作為 Web Service 客戶端實現,在程式碼中我們需要做四件事情:

  • 建立 Service 物件,即生成的 Echo_Service;
  • 使用 Service 物件得到 SEI 實現;
  • 設定 soapaction 上下文;
  • 使用 SEI 實現物件呼叫服務。

清單 3. Echo_Client
package ws.client.echo;

import java.util.Map;

import javax.xml.ws.BindingProvider;


public class Echo_Client {
	// 建立 Service 物件
static Echo_Service service = new Echo_Service();
	public void callService(String req){
		try{
		// 獲取 SEI 實現類
		Echo port = service.getEchoSOAP();
		// 設定 soapaction 上下文
 Map context = ((BindingProvider)port).getRequestContext();
		context.put("javax.xml.ws.soap.http.soapaction.uri",\
		"http://www.example.org/Echo/NewOperation");
		// 使用 SEI 實現物件呼叫服務
System.out.println("before call Echo.requestEcho()");
		System.out.println(port.requestEcho(req));
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}

	public static void main(String[] args){
		Echo_Client client = new Echo_Client();
		String req = " " + args[0];
		client.callService(req);
	}
}


編譯不通過,會提示出錯。將 \AppServer\plugins\ 目錄下的 com.ibm.jaxws.tools_6.1.0.jar 新增到專案的構建路徑中。

準備客戶端金鑰庫檔案

Web Service 客戶端的金鑰庫檔案可以是 p12 或者 JKS 格式。WS-Security 預設採用了非對稱加密的機制,因此客戶端金鑰庫檔案中應該包含客戶端的私鑰,用於對出站的 SOAP 報文進行數字簽名以及對入站的 SOAP 響應報文進行解密,還應該包含 Web Service 提供者的公鑰,用於對出站的 SOAP 報文進行加密以及對入站的 SOAP 響應報文進行數字簽名驗證。使用 ikeyman 工具(位於 \AppServer\bin\ 目錄下)建立兩個金鑰庫檔案,具體步驟是:

  1. 開啟 ikeyman 工具,選擇”Key Database File”,選擇”Key database type”為”PKCS12”,在”File Name”後面輸入”client_KeyStroe.p12”,見圖 1,選擇 OK,並在後面的提示框中輸入密碼。

    圖 1. 建立金鑰庫


  2. 在”Key database content”下面的下拉選單中選擇”Personal Certificates”,在選單中選擇”Create->New Self-Signed Certificate…”建立自簽署證照,見圖 2,在彈出框中填入證照的 標籤等資訊。



    圖 2. 建立自簽署證照


  3. 在”Personal Certificates”下,選中新建立的自簽署證照,選擇右邊的”Exprot/Import…”按鈕,將證照的公鑰匯出,供伺服器端使用。
  4. 按照步驟 1,新建一個叫做 server_cert.p12 的證照庫,在”Key database content”下面的下拉選單中選擇”Signer Certificates”,選擇右邊的”Add…”按鈕將伺服器匯出的公鑰(Base64 編碼的 ASCII 資料型別或者二進位制 DER 資料型別)新增進此證照庫。

配置客戶端策略集

針對於 WAS 6.1 提供的 Web Service 策略集,AST6.1.1.3 提供了一種在客戶端應用程式中通過配置來完成的對應的客戶端策略集。這些策略集不改動客戶端的原始碼,提供了與伺服器端對應的 Web Service 服務質量的保證,使得沒有應用伺服器或者 Web 容器環境下的客戶端能夠呼叫有服務質量要求的 Web Service。下面的章節主要描述配置客戶端的 WS-Security 策略集。

  1. 在 AST 中選擇”File->New->Other”,在彈出的對話方塊中,選擇 Web Services/Policy Set/ 目錄下的”Client Side Policy Set Attachment”,點選”Next”按鈕。
  2. 在”Client Side Policy Set Attachment”對話方塊中,選擇”Client Project”為”EchoClientStandalone”,在 Application 區域中點選”Add…”按鈕為服務端點設定策略集,見圖 3。

    圖 3. 為客戶端新增策略集


  3. 在”End Point definition Dialog”中,為應用程式選擇相應的 Service Name,Endpoint,Operation Name。為”Policy Set”選擇”WSSecurity default”,在”Binding”後面輸入任意繫結名稱,此處為”WSS-Binding-Test”,單擊”OK”按鈕,見圖 4。

    圖 4. 配置服務端點,策略集和繫結


  4. 回到”Client Side Policy Set Attachment”對話方塊中,在”Bindings Configuration”下面出現了兩個條目”WSSecurity”和”WSAddressing”,後者不需要配置繫結。選擇”WSSecurity”,單擊下面的”Configure…”按鈕,出現”Binding Configuration Dialog”對話方塊,見圖 5。

    圖 5. 配置繫結對話方塊,數字簽名配置


  5. 配置出站數字簽名。在”Binding Configuration Dialog”中,當前是”Digital Signature Configuration”頁,”Outbound Message Security Configuration”下面選的”Key Information Type”,選擇”X509ISSUER”,點選”Key Store Settings…”按鈕,在”Key Store Setting Dialog”中填入準備金鑰庫時步驟 1、2 所建立的包含自簽署證照(客戶端私鑰)的證照庫資訊,如圖 6,其中 Key Alias 就是證照的標籤。

    圖 6. 配置出站簽名證照庫


  6. 配置入站數字簽名驗證。回到”Binding Configuration Dialog”,去掉”Inbound Message Security Configuration”下的”Trust Any Certificate”,表明入站的數字簽名也需要驗證,點選下面的”Key Store Settings…”按鈕,在彈出的對話方塊中填入準備金鑰庫時步驟 4 所建立的金鑰庫(包含伺服器公鑰)相關資訊,如圖 7。

    圖 7. 配置入站簽名驗證庫


  7. 配置出站加密證照。回到”Binding Configuration Dialog”,選擇”XML Encryption Configuration”頁,”Outbound Message Security Configuration”下面選的”Key Information Type”,選擇”X509ISSUER”,點選”Key Store Settings…”按鈕,在”Key Store Setting Dialog”中填入準備金鑰庫時步驟 4 所建立的金鑰庫(包含伺服器公鑰)相關資訊,如圖 8,其中 Key Alias 就是證照的標籤。

    圖 8. 配置出站加密證照庫


  8. 配置入站解密證照。回到”Binding Configuration Dialog”,在”Inbound Message Security Configuration”下選擇”Key Store Settings…”按鈕,在”Key Store Setting Dialog”中填入準備金鑰庫時步驟 1、2 所建立的包含自簽署證照(客戶端私鑰)的證照庫資訊,如圖 6,其中 Key Alias 就是證照的標籤。
  9. 單擊”OK”,回到 Client Side Policy Set Attachment”對話方塊,選擇”Finish”,完成配置,在專案下面可以看到生成了一個 META-INF 資料夾其中包含 Policy Sets 和 WSS-Binding-Test 資料夾以及相關的策略配置,如圖 9.

    圖 9. 生成的策略檔案


測試

在 AST 中,選擇檔案 -> 匯出 ->Jar,選擇工程 EchoClientStandalone,匯出的 jar 包名稱為 EchoClient2Standalone.jar。

編寫一個 .bat 批處理檔案,設定執行客戶端所需的 Classpath。其中,需要有 com.ibm.jaxws.thinclient_6.1.0.jar,此 jar 包可以在 /AppServer/runtime/ 下面找到。wsjaas_client.conf 可以在 /AppServer/profiles//properties/ 目錄中找到。見清單 4。


清單 4. 客戶端執行批處理檔案
@echo off

if %1x == x goto USAGE

:# WAS_HOME is required 
if NOT "%WAS_HOME%" == "" goto HOMEOK
 SET CUR_DIR=%cd%
:HOMEOK
setlocal

set JAASLOGIN=-Djava.security.auth.login.config=%CUR_DIR%\wsjaas_client.conf

:# Edit the lines below if your machine has products installed to different paths
set JAVA_HOME=C:\IBM\Java50\jre
set PATH=%JAVA_HOME%\bin;%PATH%
set CLASSPATH=%CUR_DIR%\com.ibm.jaxws.thinclient_6.1.0.jar;\
%CUR_DIR%\EchoClient2Standalone.jar;.;

:# 
java %JAASLOGIN% -cp "%CLASSPATH%" ws.client.echo.Echo_Client %1
goto END
###################################
:USAGE
@echo The program takes 1 parameters as described below
@echo "USAGE : runEchoClient "
@echo "SAMPLE: runEchoClient hello"
goto END
:END

在執行客戶端的時候,執行此客戶端需要 IBM jre 5.0(或者更高版本),可以使用 WAS 6.1 下的 jre 來執行。

在執行客戶端之前,我們在 AST 中開啟附帶的 TCP/IP Monitor 來監控報文。假設 Web Service 服務端提供的服務埠是 9085,在 AST 中選擇視窗 -> 顯示檢視 -> 其他 -> 除錯 ->TCP/IP 監視器,新建一個 TCP/IP 監視器並填入參入,如圖 10。


圖 10. 建立 TCP/IP 監視器

在構建客戶端之前,確保此 Web Service 服務端已經部署到 WAS6.1 上,並且正確配置了 WS-Security 策略集,保證其正在執行中。

將 EchoClient2Standalone.jar,com.ibm.jaxws.thinclient_6.1.0.jar,以及執行客戶端的批處理檔案放置於同一個目錄,執行批處理檔案,檢視執行結果,見圖 11。


圖 11. 執行結果

檢視 TCP/IP 監視器。從客戶端發向伺服器端的 SOAP 信封,經過客戶端 WS-Security 策略集的加密和簽名,見清單 5。


清單 5. 客戶端發向伺服器端的 SOAP 信封

MIIBvT...BnesE0= hS6nfYE9axFgay+gorMEo0I4GfY= OULe5mAxLwYibommo1Ui/...1gvtagYQ= TnqRmYse3nLjO+cw14f7...20C1MzPPA== 2008-07-10T09:21:29.875Z http://9.186.110.205:9095/EchoWeb/Echo urn:uuid:CD3CB273ED6FC2523A1215681690036 http://www.example.org/Echo/NewOperation
hrGbauq8Y7CefUCqZoZtYy6q0.../3pqVpOs=

伺服器端解密並驗證之後,接受了客戶端的 SOAP 信封。從伺服器端返回的 SOAP 信封,經過了伺服器端 WS-Security 策略集的加密和簽名,被 TCP/IP 監視器捕獲到,見清單 6。


清單 6. 伺服器端返回的 SOAP 信封

MIIBvTCCA...6qBnesE0= MIIBvTCCA...4QsyJ3IM= P3o2ROBqCC...WT8zbKkXSzk0= gWuUf6RbFmaL8h1TS/yv.../JvVe40LQ3S 2008-07-10T09:19:17.578Z http://www.example.org/Echo/Echo/requestEchoResponse urn:uuid:CD3CB273ED6FC2523A1215681690036
o1ATY1fu4L4GvlNqjUvIADJ...iTXScQZY4=

結束語

滿足 WS-Security 的 Web Service 服務端需要同樣滿足 WS-Security 的客戶端來進行呼叫。對於一個在 WAS6.1 環境下的 Web Service 客戶端(一個 J2EE 應用),應用伺服器提供了針對 WS-Security 的 QoS 支援。針對執行時為單機 J2SE 的 Web Service 客戶端的情況,本文通過一個例項展示瞭如何使用 AST 構建這樣的一個不依賴於應用伺服器或者 Web 容器的 Standalone 的 JAX-WS Web Service 客戶端,並且此客戶端符合 WS-Security 標準,能夠呼叫滿足 WS-Security 的服務端提供的 Web 服務,進行安全的互動。除了 WS-Security,AST 還提供其他的策略集支援,包括 LTPA RAMP,SecureConversation,WSAddressing,WSHTTPS,WSReliableMessaging,WSTransaction 等,能夠滿足 WAS 伺服器端的各種服務質量的要求。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-442886/,如需轉載,請註明出處,否則將追究法律責任。

相關文章