建立安全的AXIS服務

 

建立安全的AXIS服務
在前面的文章中,我們實現了最簡單的AXIS服務。現在我們一起來討論一下Web服務的安全問題。
根據應用的對安全要求的級別不同,可以採用不同的方式來實現安全性,以下是目前最常用的一些實現方式(從低到高排列):
    1、J2EE Web應用默認的訪問控制(數據是明文的); 
    2、使用axis的Handler進行訪問控制(數據是明文的); 
    3、使用Servlet過濾器(Filter)進行訪問控制(數據是明文的); 
    4、使用SSL/HTTPS協議來傳輸(加密的數據傳輸協議); 
    5、使用WS-Security規範對信息進行加密與身份認證(數據被加密傳輸)。
我們僅討論第2、4、5種實現方式。在此之前我們先來了解一下AXIS自帶的一個工具SOAPMonitor。
一、SOAPMonitor的使用
  打開http://localhost:8080/axis/進入AXIS的主頁面,你會看見:
   SOAPMonitor-[disabled by default for security reasons] ,默認狀態下其是不可用的,現在我們就來激活它。
   
1、到目錄%TOMCAT_HOME%/webapps/axis下,你會找到SOAPMonitorApplet.java,在命令行中編譯它:
        javac -classpath %AXIS_HOME%/lib/axis.jar SOAPMonitorApplet.java
   編譯完之後你會看見目錄下多了很多CLASS文件,它們的名字是SOAPMonitorApplet*.class

2、在目錄%TOMCAT_HOME%/webapps/axis/WEB-INF下打開server-config.wsdd文件,將下面的兩部分代碼直
   接加入其中相應的位置
   第一部分:
      <handler name="soapmonitor"   type="java:org.apache.axis.handlers.SOAPMonitorHandler">
        <parameter name="wsdlURL"   value="/axis/SOAPMonitorService-impl.wsdl"/>
        <parameter name="namespace"   value="http://tempuri.org/wsdl/2001/12/SOAPMonitorService-impl.wsdl"/>
        <parameter name="serviceName" value="SOAPMonitorService"/>
        <parameter name="portName" value="Demo"/>
      </handler>
   第二部分:
      <service name="SOAPMonitorService" provider="java:RPC">
        <parameter name="allowedMethods" value="publishMessage"/>
        <parameter name="className"   value="org.apache.axis.monitor.SOAPMonitorService"/>
        <parameter name="scope" value="Application"/>
      </service>

3、選擇你要監控的服務
   以上次的HelloWorld服務爲例,在server-config.wsdd中你會找到這段代碼
    <service name="HelloWorld" provider="java:RPC">
       <parameter name="allowedMethods" value="sayHello"/>
       <parameter name="className" value="HelloWorld"/>
    </service>
   在這段代碼中加入以下的代碼:
    <requestFlow>
      <handler type="soapmonitor"/>
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
    </responseFlow>
   最後的樣子是:
    <service name="HelloWorld" provider="java:RPC">
    <requestFlow>
      <handler type="soapmonitor"/>
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
    </responseFlow>
    <parameter name="allowedMethods" value="sayHello"/>
    <parameter name="className" value="HelloWorld"/>
    </service>
   這樣HelloWorld服務就被監控了
   
4、啓動Tomcat,打開http://localhost:8080/axis/SOAPMonitor,你就會看到Applet界面,在
   jbuilder2005中運行我們上次寫的客戶端程序 TestClient.java。OK!你會在Applet界面看
   見客戶端與服務器端互發的XML內容,注意這裏是明文!
   
二、使用axis的Handler進行訪問控制(對安全要求不高時推薦)
   axis爲Web服務的訪問控制提供了相關的配置描述符,並且提供了一個訪問控制的簡單  Handler。默認情況下,你只要在配置描述符中添加用戶,然後在Web服務器的部署描述符中自動允許的角色即可。

1、在axis的配置文件users.lst(位於WEB-INF目錄下)中添加一個用戶,如"ronghao1111",表示
   用戶名爲ronghao,密碼爲1111。
   
2、把例HelloWorld的Web服務重新部署(新加的部分已標出)
    <service name="HelloWorld" provider="java:RPC">
    <requestFlow>
      <handler type="soapmonitor"/>
      <handler type="Authenticate"/>  //新加的AXIS自帶的Handler
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
    </responseFlow>
    <parameter name="allowedMethods" value="sayHello"/>
    <parameter name="allowedRoles" value="ronghao"/>    //注意,這裏是新加的部分!
    <parameter name="className" value="HelloWorld"/>
   </service>
  在這個部署描述符中,指定HelloWorld服務只能被ronghao訪問
   
3、修改客戶端程序 TestClient.java,增加訪問用戶名、密碼(新加的部分已標出)
   TestClient.java

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.rpc.ParameterMode;

public class TestClient
{
   public static void main(String [] args) throws Exception {
   String endpoint = "http://localhost:" +"8080"+ "/axis/HelloWorld";

       Service  service = new Service();  
       Call     call    = (Call) service.createCall();
       call.getMessageContext().setUsername("ronghao");//  用戶名。
       call.getMessageContext().setPassword("1111");//   密碼
     call.setTargetEndpointAddress( new java.net.URL(endpoint) );

     call.setOperationName( "sayHello" );
     String res = (String) call.invoke( new Object[] {} );

     System.out.println( res );
   }
}
  執行TestClient,能夠順利訪問Web服務;如果修改用戶名或者密碼,那麼就不能訪問 。同樣,
  你在http://localhost:8080/axis/SOAPMonitor中看到的請求和響應的XML是明文!
  
三、使用SSL/HTTPS協議來傳輸
    Web服務也可以使用SSL作爲傳輸協議。雖然JAX-RPC並沒有強制規定是否使用SSL協議,但在tomcat
    下使用HTTPS協議。
1、使用JDK自帶的工具創建密匙庫和信任庫。

  1)通過使用以下的命令來創建服務器端的密匙庫:
   keytool -genkey -alias Server -keystore server.keystore -keyalg RSA
  輸入keystore密碼:  changeit
  您的名字與姓氏是什麼?
  [Unknown]:  Server
  您的組織單位名稱是什麼?
  [Unknown]:  ec
  您的組織名稱是什麼?
  [Unknown]:  ec
  您所在的城市或區域名稱是什麼?
  [Unknown]:  beijing
  您所在的州或省份名稱是什麼?
  [Unknown]:  beijing
  該單位的兩字母國家代碼是什麼
  [Unknown]:  CN
CN=Server, OU=ec, O=ec, L=beijing, ST=beijing, C=CN 正確嗎?
  [否]:  y

輸入<Server>的主密碼
        (如果和 keystore 密碼相同,按回車):
   以上命令執行完成後,將獲得一個名爲server.keystore的密匙庫。
   
  2)生成客戶端的信任庫。首先輸出RSA證書:
  keytool -export -alias Server -file test_axis.cer -storepass changeit -keystore server.keystore
  然後把RSA證書輸入到一個新的信任庫文件中。這個信任庫被客戶端使用,被用來驗證服務器端的身份。
  keytool -import -file test_axis.cer -storepass changeit -keystore client.truststore -alias serverkey -noprompt
  以上命令執行完成後,將獲得一個名爲client.truststore的信任庫。
  
  3)同理生成客戶端的密匙庫client.keystore和服務器端的信任庫server.truststore.方便起見給出.bat文件
     gen-cer-store.bat內容如下:
     set SERVER_DN="CN=Server, OU=ec, O=ec, L=BEIJINGC, S=BEIJING, C=CN"
     set CLIENT_DN="CN=Client, OU=ec, O=ec, L=BEIJING, S=BEIJING, C=CN"
     set KS_PASS=-storepass changeit
     set KEYINFO=-keyalg RSA

     keytool -genkey -alias Server -dname %SERVER_DN% %KS_PASS% -keystore server.keystore %KEYINFO% -keypass changeit
     keytool -export -alias Server -file test_axis.cer %KS_PASS% -keystore server.keystore
     keytool -import -file test_axis.cer %KS_PASS% -keystore client.truststore -alias serverkey -noprompt

     keytool -genkey -alias Client -dname %CLIENT_DN% %KS_PASS% -keystore client.keystore %KEYINFO% -keypass changeit
     keytool -export -alias Client -file test_axis.cer %KS_PASS% -keystore client.keystore
     keytool -import -file test_axis.cer %KS_PASS% -keystore server.truststore -alias clientkey -noprompt
     
  好的,現在我們就有了四個文件:server.keystore,server.truststore,client.keystore,client.truststore
  
2、更改Tomcat的配置文件(server.xml),增加以下部署描述符:(其實裏面有,只是被註釋掉了)
      <Connector port="8440" 
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="true" keystoreFile="f:/server.keystore" keystorePass="changeit"
                 truststoreFile="f:/server.truststore" truststorePass="changeit"
               sslProtocol="TLS" />

3、把HelloWorld重新部署一次,在server-config.wsdd中修改如下部署代碼。(還原了而已)
    <service name="HelloWorld" provider="java:RPC">
    <requestFlow>
      <handler type="soapmonitor"/>
    </requestFlow>
    <responseFlow>
      <handler type="soapmonitor"/>
    </responseFlow>
    <parameter name="allowedMethods" value="sayHello"/>
    <parameter name="className" value="HelloWorld"/>
    </service>
    
4、修改客戶端程序 TestClient.java(修改的部分已標出)

   public class TestClient
{
   public static void main(String [] args) throws Exception {
   String endpoint = "https://localhost:" +"8440"+ "/axis/HelloWorld";//注意區別在這裏!https!

       Service  service = new Service();  
       Call     call    = (Call) service.createCall();
     call.setTargetEndpointAddress( new java.net.URL(endpoint) );

     call.setOperationName( "sayHello" );
     String res = (String) call.invoke( new Object[] {} );

     System.out.println( res );
   }
}

5、最後使用命令來執行客戶端程序

java -cp %AXISCLASSPATH%
     -Djavax.net.ssl.keyStore=client.keystore 
     -Djavax.net.ssl.keyStorePassword=changeit 
     -Djavax.net.ssl.trustStore=client.truststore 
     TestClient

四、使用WS-Security規範對信息進行加密與身份認證
    我們打算用Handler結合WSSecurity實現Web服務安全(Handler的有關內容請參閱AXIS學習筆記(二))
    設想流程:用WSClientRequestHandler.java位於客戶端對客戶端發出的XML文檔進行加密
                WSServerRequestHandler.java位於服務器端對客戶端發出的加密後的XML文檔進行解密
                WSServerResponseHandler.java位於服務器端對服務器端返回的XML文檔進行加密
                WSClientResponseHandler.java位於客戶端對服務器端返回的XML文檔進行解密
                
 1、使用ISNetworks安全提供者,ISNetworks實現了RSA加密、解密算法。
    當然,你也可以使用其它的安全提供者,並且可以使用不同的加密算法。
    ISNetworks相關包ISNetworksProvider.jar。拷貝到%TOMCAT_HOME%     /webapps/axis/WEB-INF/lib
    
 2、Trust Services Integration Kit提供了一個WS-Security實現。你可以從http://www.xmltrustcenter.org獲得相關庫文件,分別是ws-security.jar和tsik.jar。ws-security.jar中包含一個WSSecurity類,我們使用它來對XML進行數字簽名和驗證,加密與解密。同樣拷貝到%TOMCAT_HOME%/webapps/axis/WEB-INF/lib

 3、創建密匙庫和信任庫。(見上文,一模一樣!)
     
 4、框架結構
    WSClientHandler.java  //基類,包含了一些公用方法
    WSClientRequestHandler.java //繼承於WSClientHandler.java,調用WSHelper.java對客戶端發出的XML文檔進行加密
    WSClientResponseHandler.java //繼承於WSClientHandler.java,調用WSHelper.java對服務器端返回的XML文檔進行解密
    WSServerHandler.java //基類,包含了一些公用方法
    WSServerRequestHandler.java //繼承於WSServerHandler.java,調用WSHelper.java對客戶端發出的加密後的XML文檔進行解密
    WSServerResponseHandler.java//繼承於WSServerHandler.java,調用WSHelper.java對服務器端返回的XML文檔進行加密
    WSHelper.java //核心類,對SOAP消息簽名、加密、解密、身份驗證
    MessageConverter.java  //幫助類,Document、SOAP消息互相轉換
  
 5、具體分析(在此強烈建議看一下tsik.jar的API)
    WSHelper.java 
    public class WSHelper {
        static String PROVIDER="ISNetworks";//JSSE安全提供者。
  //添加JSSE安全提供者,你也可以使用其它安全提供者。只要支持DESede算法。這是程序裏動態加載還可以在JDK中靜態加載
        static
        {
         java.security.Security.addProvider(new com.isnetworks.provider.jce.ISNetworksProvider());
    }
    /**
     *對XML文檔進行數字簽名。
     */
        public static void sign(Document doc, String keystore, String storetype,
                                                String storepass, String alias, String keypass) throws Exception {
                FileInputStream fileInputStream = new FileInputStream(keystore);
                java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
                keyStore.load(fileInputStream, storepass.toCharArray());
                PrivateKey key = (PrivateKey)keyStore.getKey(alias, keypass.toCharArray());
                X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
                SigningKey sk = SigningKeyFactory.makeSigningKey(key);
                KeyInfo ki = new KeyInfo();
                ki.setCertificate(cert);
                WSSecurity wSSecurity = new WSSecurity();//ws-security.jar中包含的WSSecurity類
                wSSecurity.sign(doc, sk, ki);//簽名。


        }
    /**
     *對XML文檔進行身份驗證。
     */
        public static boolean verify(Document doc, String keystore, String storetype,
                                                String storepass) throws Exception {
                FileInputStream fileInputStream = new FileInputStream(keystore);
                java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
                keyStore.load(fileInputStream, storepass.toCharArray());
                TrustVerifier verifier = new X509TrustVerifier(keyStore);
                WSSecurity wSSecurity = new WSSecurity();
                MessageValidity[] resa = wSSecurity.verify(doc, verifier, null,null);
                if (resa.length > 0)
                        return resa[0].isValid();
                return false;
        }
   /**
    *對XML文檔進行加密。必須有JSSE提供者才能加密。
    */
        public static void encrypt(Document doc, String keystore, String storetype,
                                                String storepass, String alias) throws Exception {
                try
                {
                FileInputStream fileInputStream = new FileInputStream(keystore);
                java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
                keyStore.load(fileInputStream, storepass.toCharArray());
                X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
                PublicKey pubk = cert.getPublicKey();
                KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede",PROVIDER);
                keyGenerator.init(168, new SecureRandom());
                SecretKey key = keyGenerator.generateKey();
                KeyInfo ki = new KeyInfo();
                ki.setCertificate(cert);
                WSSecurity wSSecurity = new WSSecurity();
                //加密。
                wSSecurity.encrypt(doc, key, AlgorithmType.TRIPLEDES, pubk, AlgorithmType.RSA1_5, ki);
        }
        catch(Exception e)
        {
                e.printStackTrace();
        }
        }
    /**
     *對文檔進行解密。
     */
        public static void decrypt(Document doc, String keystore, String storetype,
                                                String storepass, String alias, String keypass) throws Exception {
                FileInputStream fileInputStream = new FileInputStream(keystore);
                java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
                keyStore.load(fileInputStream, storepass.toCharArray());
                PrivateKey prvk2 = (PrivateKey)keyStore.getKey(alias, keypass.toCharArray());

                WSSecurity wSSecurity = new WSSecurity();
                //解密。

                wSSecurity.decrypt(doc, prvk2, null);
                WsUtils.removeEncryptedKey(doc);//從 WS-Security Header中刪除 EncryptedKey 元素
        }

        public static void removeWSSElements(Document doc) throws Exception {
                WsUtils.removeWSSElements(doc);// 刪除WSS相關的元素。
        }

}

   WSClientHandler.java
   //繼承自org.apache.axis.handlers.BasicHandler即AXIS內在的
   public class WSClientHandler extends BasicHandler{
  protected String keyStoreFile ;
  protected  String keyStoreType ="JKS";//默認
  protected String keyStorePassword ;
  protected String keyAlias ;
  protected String keyEntryPassword ;
  protected String trustStoreFile ;
  protected String trustStoreType = "JKS";//默認
  protected String trustStorePassword ;
  protected String certAlias ;

  public void setInitialization(String keyStoreFile,String keyStoreType,String keyStorePassword,
                 String keyAlias,String keyEntryPassword,String trustStoreFile,
                 String trustStoreType,String trustStorePassword,String certAlias){
  this.keyStoreFile=keyStoreFile;
  this.keyStoreType=keyStoreType;
  this.keyStorePassword=keyStorePassword;
  this.keyAlias=keyAlias;
  this.keyEntryPassword=keyEntryPassword;
  this.trustStoreFile=trustStoreFile;
  this.trustStoreType=trustStoreType;
  this.trustStorePassword=trustStorePassword;
  this.certAlias=certAlias;
}
  public void setInitialization(String keyStoreFile,String keyStorePassword,
                String keyAlias,String keyEntryPassword,String trustStoreFile,
                String trustStorePassword,String certAlias){
  this.keyStoreFile=keyStoreFile;
  this.keyStorePassword=keyStorePassword;
  this.keyAlias=keyAlias;
  this.keyEntryPassword=keyEntryPassword;
  this.trustStoreFile=trustStoreFile;
  this.trustStorePassword=trustStorePassword;
  this.certAlias=certAlias;
}
  public void invoke(MessageContext messageContext) throws AxisFault {//在這個方法裏對XML文檔進行處理
    //do nothing now!
  }
  public void onFault(MessageContext msgContext) {
    System.out.println("處理錯誤,這裏忽略!");
        }
}
  
  WSClientRequestHandler.java
  public class WSClientRequestHandler extends WSClientHandler{
  public void invoke(MessageContext messageContext) throws AxisFault {
    try {

     SOAPMessage soapMessage = messageContext.getMessage();
     Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage); //soapMessage轉換爲Document
     WSHelper.sign(doc, keyStoreFile, keyStoreType,keyStorePassword, keyAlias, keyEntryPassword); //數字簽名
     WSHelper.encrypt(doc, trustStoreFile, trustStoreType, trustStorePassword, certAlias); //加密
     soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc); 
//處理後的Document再轉換回soapMessage
     messageContext.setMessage(soapMessage);
     } catch (Exception e){
     System.err.println("在處理響應時發生以下錯誤: " + e);
      e.printStackTrace();  }
        }
}  

  WSClientResponseHandler.java
  public class WSClientResponseHandler extends WSClientHandler{
  public void invoke(MessageContext messageContext) throws AxisFault {
    try {

            SOAPMessage soapMessage =  messageContext.getCurrentMessage();
            Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage);

        WSHelper.decrypt(doc, keyStoreFile, keyStoreType,
                            keyStorePassword, keyAlias, keyEntryPassword);//解密

            WSHelper.verify(doc, trustStoreFile, trustStoreType, trustStorePassword);//驗證
            WSHelper.removeWSSElements(doc);
            soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
            messageContext.setMessage(soapMessage);
    } catch (Exception e){
            e.printStackTrace();
            System.err.println("在處理響應時發生以下錯誤: " + e);
                         }

        }
}    
   
   WSServerHandler.java 
   public class WSServerHandler extends BasicHandler{
  protected String keyStoreFile ;
  protected  String keyStoreType ="JKS";//默認
  protected String keyStorePassword ;
  protected String keyAlias ;
  protected String keyEntryPassword ;
  protected String trustStoreFile ;
  protected String trustStoreType = "JKS";//默認
  protected String trustStorePassword ;
  protected String certAlias ;

  public void invoke(MessageContext messageContext) throws AxisFault {
    //do nothing now!
  }
  public void onFault(MessageContext msgContext) {
    System.out.println("處理錯誤,這裏忽略!");
        }
  public void init() { //初始化,從配置文件server-config.wsdd中讀取屬性
    keyStoreFile = (String)getOption("keyStoreFile");
    if(( keyStoreFile== null) )
      System.err.println("Please keyStoreFile configured for the Handler!");
    trustStoreFile = (String)getOption("trustStoreFile");
     if((  trustStoreFile== null) )
    System.err.println("Please trustStoreFile configured for the Handler!");
    keyStorePassword = (String)getOption("keyStorePassword");
     if(( keyStorePassword== null) )
    System.err.println("Please keyStorePassword configured for the Handler!");
    keyAlias = (String)getOption("keyAlias");
     if(( keyAlias== null) )
    System.err.println("Please keyAlias configured for the Handler!");
    keyEntryPassword = (String)getOption("keyEntryPassword");
     if(( keyEntryPassword== null) )
    System.err.println("Please keyEntryPassword configured for the Handler!");
    trustStorePassword = (String)getOption("trustStorePassword");
     if(( trustStorePassword== null) )
    System.err.println("Please trustStorePassword configured for the Handler!");
    certAlias = (String)getOption("certAlias");
    if ((certAlias==null))
        System.err.println("Please certAlias configured for the Handler!");
    if ((getOption("keyStoreType")) != null)
       keyStoreType = (String)getOption("keyStoreType");
    if ((getOption("trustStoreType")) != null)
       trustStoreType = (String)getOption("trustStoreType");
    }
}         
    
    WSServerRequestHandler.java 
    public class WSServerRequestHandler extends WSServerHandler{
  public void invoke(MessageContext messageContext) throws AxisFault {
    try {
      SOAPMessage msg = messageContext.getCurrentMessage();
            Document doc = MessageConverter.convertSoapMessageToDocument(msg);
            System.out.println("接收的原始消息:");
           msg.writeTo(System.out);
        WSHelper.decrypt(doc, keyStoreFile, keyStoreType,
                            keyStorePassword, keyAlias, keyEntryPassword);//解密

            WSHelper.verify(doc, trustStoreFile, trustStoreType, trustStorePassword);//驗證
            WSHelper.removeWSSElements(doc);
            msg = MessageConverter.convertDocumentToSOAPMessage(doc);
            System.out.println("懷原後的原始消息:");
            msg.writeTo(System.out);
            messageContext.setMessage(msg);
    } catch (Exception e){
            e.printStackTrace();
            System.err.println("在處理響應時發生以下錯誤: " + e);
                         }

        }
}   
     
     WSServerResponseHandler.java
     public class WSServerResponseHandler extends WSServerHandler{
  public void invoke(MessageContext messageContext) throws AxisFault {
    try {

     SOAPMessage soapMessage = messageContext.getMessage();
       System.out.println("返回的原始消息:");
         soapMessage.writeTo(System.out);
      Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage);

        WSHelper.sign(doc, keyStoreFile, keyStoreType,
          keyStorePassword, keyAlias, keyEntryPassword);//數字簽名
       WSHelper.encrypt(doc, trustStoreFile, trustStoreType,//加密
        trustStorePassword, certAlias);

       soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
       System.out.println("返回的加密後的消息:");
       soapMessage.writeTo(System.out);
       messageContext.setMessage(soapMessage);
        } catch (Exception e){
        System.err.println("在處理響應時發生以下錯誤: " + e);
         e.printStackTrace();
         }

        }
}

6、應用
   爲方便使用,把上述文件打包爲ws-axis.jar,放入%TOMCAT_HOME%/webapps/axis/WEB-INF/lib
   
   1)把HelloWorld重新部署一次,在server-config.wsdd中修改如下部署代碼。
       <service name="HelloWorld" provider="java:RPC">
         <parameter name="allowedMethods" value="*"/>
         <parameter name="className" value="HelloWorld"/>
         <requestFlow>
           <handler type="soapmonitor"/>
           <handler type="java:com.ronghao.WSAxis.WSServerRequestHandler">
              <parameter name="keyStoreFile" value="f:/server.keystore"/>
              <parameter name="trustStoreFile" value="f:/server.truststore"/>
              <parameter name="keyStorePassword" value="changeit"/>
              <parameter name="keyAlias" value="Server"/>
              <parameter name="keyEntryPassword" value="changeit"/>
              <parameter name="trustStorePassword" value="changeit"/>
              <parameter name="certAlias" value="clientkey"/>
           </handler>
        </requestFlow>
        <responseFlow>
           <handler type="soapmonitor"/>
           <handler type="java:com.ronghao.WSAxis.WSServerResponseHandler">
              <parameter name="keyStoreFile" value="f:/server.keystore"/>
              <parameter name="trustStoreFile"  value="f:/server.truststore"/>
              <parameter name="keyStorePassword" value="changeit"/>
              <parameter name="keyAlias" value="Server"/>
              <parameter name="keyEntryPassword" value="changeit"/>
              <parameter name="trustStorePassword" value="changeit"/>
              <parameter name="certAlias" value="clientkey"/>
           </handler>
        </responseFlow>
     </service>
     
    2)修改客戶端程序 TestClient.java(修改的部分已標出,記着導入ws-axis.jar)
    import javax.xml.namespace.QName;
    import org.apache.axis.client.Call;
    import org.apache.axis.client.Service;
    import com.ronghao.WSAxis.*;
    
    public class WSSClient1
{
    public static void main(String [] args)
    {
        try {
                //服務端的url,需要根據情況更改。
            String endpointURL = "http://localhost:8080/axis/services/HelloWorld";
            Service svc = new Service();

            WSClientHandler handler=new WSClientRequestHandler();
//注意新加的HANDLER
            handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
                "f:/client.truststore","changeit","serverkey");//初始化
            WSClientHandler handlee=new WSClientResponseHandler();
//注意新加的HANDLER
            handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
                "f:/client.truststore","changeit","serverkey");//初始化
                     Call call =(Call)svc.createCall();
                     call.setClientHandlers(handler,handlee);//添加Handler
                     call.setTargetEndpointAddress(new java.net.URL(endpointURL));
                     call.setOperationName(new QName("sayHello"));

                     String result = (String) call.invoke( new Object [] {});
                     System.out.println("the result"+result);

        } catch (Exception e) {
                e.printStackTrace();
        }
    }


}
   運行的時候http://localhost:8080/axis/SOAPMonitor中看到的請求的XML就已加密!
   
總結
   這裏對代碼的解釋是不夠的,很多概念沒有提到。建議你最好看tsik.jar和AXIS的API深入瞭解。另外對ws-axis.jar的加解密實現打算運用apache的wss4j,相關網址http://ws.apache.org/ws-fx/wss4j/。不過這個東西也應該夠用了暫時。所有的源文件在附件中附件:soapTest.zip(279K) 

選自:http://bound.blogdriver.com/bound/1120157.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章