posts - 193,  comments - 520,  trackbacks - 0

          四、使用WS-Security規范對信息進行加密與身份認證
              
          我們打算用Handler結合WSSecurity實現Web服務安全
              
          設想流程:用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.jartsik.jarws-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  //
          幫助類,DocumentSOAP消息互相轉換
            
           5
          、具體分析(在此強烈建議看一下tsik.jarAPI
              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(
          168new 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.jarAXISAPI深入了解。另外對ws-axis.jar的加解密實現打算運用apachewss4j,相關網址http://ws.apache.org/ws-fx/wss4j/。不過這個東西也應該夠用了暫時。



          http://www.aygfsteel.com/ronghao 榮浩原創,轉載請注明出處:)
          posted on 2007-06-12 16:20 ronghao 閱讀(2256) 評論(4)  編輯  收藏 所屬分類: SOA、BPM

          FeedBack:
          # re: 建立安全的AXIS服務(下)
          2007-06-14 00:10 | IT進行時
          收藏  回復  更多評論
            
          # re: 建立安全的AXIS服務(下)
          2007-08-01 11:31 | ehe
          不錯  回復  更多評論
            
          # re: 建立安全的AXIS服務(下)
          2007-11-01 13:51 | 盧寧
          ws-security.jar和tsik.jar這兩個包有沒有阿?
          如果有能不能發給我luning83@126.com
          萬分感謝!!!  回復  更多評論
            
          # re: 建立安全的AXIS服務(下)
          2007-11-06 18:04 | ronghao
          @盧寧
          現在沒有了:(  回復  更多評論
            
          <2007年6月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          關注工作流和企業業務流程改進。現就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

          常用鏈接

          留言簿(38)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          常去的網站

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 长治县| 伊川县| 太保市| 临江市| 津南区| 西青区| 阜新市| 安新县| 南涧| 阿坝| 巩留县| 九龙坡区| 林芝县| 平和县| 张家港市| 清水河县| 通河县| 安康市| 光泽县| 周至县| 乌兰浩特市| 满洲里市| 青神县| 永清县| 章丘市| 龙川县| 高台县| 肃北| 大安市| 兴化市| 新昌县| 建阳市| 张家港市| 德化县| 垦利县| 娄烦县| 新宾| 云阳县| 绩溪县| 冀州市| 都江堰市|