打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
AXIS学习笔记(四)(建立安全的AXIS服务下)
四、使用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) 
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
AXIS完全总结
实现安全的AXIS Web服务,第2部分
AXIS实现Web服务深入篇
利用AXIS开发Webservice(二) —— WSDD的一些高级特性
九、WebService中文件传输
WebService大讲堂之Axis2(5):会话(Session)管理
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服