posts - 495,comments - 227,trackbacks - 0

          在AXIS服務間傳遞JavaBean及其安全解決
          ?這是AXIS學習筆記的最后一篇。在前面我們討論了最簡單的HelloWorld服務,客戶端并沒有向服務器端
          ?傳遞參數,現在我們來傳傳JavaBean。當然,也可以傳遞你自己定義的JAVA類,但那樣你必須自己創建
          ?專門的XML序列化器和反序列化器
          而對JavaBean,AXIS提供了現成的序列化器。(有人說:懶惰是程序員最大的美德,我喜歡,所以我就傳傳JavaBean)
          ?
          ?一、服務器端
          ??1、CLASS類兩個Order.class,OrderTest.class,位于%TOMCAT_HOME%\webapps\axis\WEB-INF\classes下
          ?????這兩個類都直接給出源碼,不再說明
          ?????Order.java
          ?????public?class?Order?{
          ????????private?String?id;
          ????????private?String?name;
          ????????public?void?setId(String?id){
          ???????????this.id=id;
          ????????}
          ????????public?String?getId(){
          ???????????return?id;
          ????????}
          ????????public?void?setName(String?name){
          ????????????this.name=name;
          ????????}
          ????????public?String?getName(){
          ????????????return?name;
          ????????}
          ??????}
          ??????
          ????OrderTest.java
          ????public?class?OrderTest?{
          ??????public?Order?returnOrder(Order?order){
          ????????Order?newOrder=new?Order();
          ????????if(order.getId().equals("1"))
          ???????????newOrder.setName("ronghao");
          ????????else?newOrder.setName("haorong");
          ????????return?newOrder;
          ??????}
          ????}
          ????
          ??2、修改服務器端配置文件server-config.wsdd
          ???在server-config.wsdd中相應位置添加以下代碼
          ??<service?name="Order"?provider="java:RPC">
          ????<parameter?name="allowedMethods"?value="returnOrder"/>
          ????<parameter?name="className"?value="OrderTest"/>
          ????<beanMapping?languageSpecificType="java:Order"?qname="ns1:Order"?
          ?????????xmlns:ns1="urn:BeanService"/>
          ??</service>
          ??可以看到和前面的發布服務代碼相比僅多了一行代碼
          ????<beanMapping?languageSpecificType="java:Order"?qname="ns1:Order"?
          ?????????xmlns:ns1="urn:BeanService"/>
          ???languageSpecificType屬性指定JavaBean類文件位置,例如:
          ???languageSpecificType="java:com.ronghao.axis.Order"
          ???qname屬性指定JavaBean類的名字
          ???其他是固定的。
          ???
          ?二、客戶端
          ???客戶端類文件一個OrderClient.class,代碼如下(變化的部分加注釋):
          ???public?class?OrderClient
          {

          ????public?static?void?main(String?args[])
          ????????throws?Exception
          ????{
          ????????String?endpoint?=?"http://localhost:8080/axis/services/Order";??//服務所在位置
          ????????Order?order=new?Order();???//JavaBean
          ????????order.setId("1");
          ????????Service?service?=?new?Service();
          ????????Call?call?=?(Call)service.createCall();
          ????????//注冊JavaBean,注意和server-config.wsdd中的配置代碼比較
          ????????QName?qn?=?new?QName("urn:BeanService",?"Order");
          ????????call.registerTypeMapping(Order.class,?qn,?new?BeanSerializerFactory(Order.class,?qn),?
          ????????????????????????????????new?BeanDeserializerFactory(Order.class,?qn));
          ????????String?name="no!";
          ????????try
          ????????{
          ????????????call.setTargetEndpointAddress(new?URL(endpoint));
          ????????????//調用的服務器端方法
          ????????????call.setOperationName(new?QName("Order",?"returnOrder"));
          ????????????//設定傳入的參數,這里qn即Order.class
          ????????????call.addParameter("arg1",?qn,?ParameterMode.IN);
          ????????????//設定返回的參數是Order.class
          ????????????call.setReturnType(qn,?Order.class);
          ????????????Order?result?=?(Order)call.invoke(new?Object[]?{
          ????????????????order
          ????????????});
          ????????????if(result?!=?null)
          ????????????????name?=?result.getName();
          ????????}
          ????????catch(Exception?e)
          ????????{
          ????????????System.err.println(e);
          ????????}
          ????????System.out.println(name);
          ????}
          }
          ??OK!運行一下,就可以看到返回了"ronghao"。
          ??
          ??和上一篇文章一樣,我們不容許在網絡中傳遞XML是明文,于是需要加密和驗證。這里我們繼續采用上次所講的框架。(已打包成ws-axis.jar)
          ??
          ?一、修改服務器端配置文件server-config.wsdd(和上一文章一模一樣!不再羅嗦)
          ??在server-config.wsdd中相應位置添加以下代碼
          ?????????<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>
          ????????
          ?二、客戶端(區別就在這里,注意!!)
          ??首先在這里要說一下,客戶端代碼編寫困擾了我很長一段時間(整整一天),因為它并不象我想象的那么簡單,當然解決起來還是挺簡單的:)問題的解決經歷了三個階段
          ??
          ??第一階段:
          ???在這個階段我想當然的在OrderClient.class中加入了如下代碼:
          ????????????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.setClientHandlers(handler,handlee);//添加Handler
          ???這個方法也是我在上一文章里介紹的,結果拋出以下異常:
          ???faultString:?org.xml.sax.SAXException:?Deserializing?parameter
          ????&apos;newProfileReturn&apos;:??could?not?find?deserializer?for?type
          ???{urn:BeanService?Order}SerializableProfile
          ???也就是說不能正常解析XML文件,于是理所當然的郁悶了,覺得代碼中肯定漏設了CALL的一個屬性,于是查看AXIS的源代碼,沒有結果!轉機出現在下面一行代碼,在不斷的拋出異常中我修改了代碼
          ???將call.setClientHandlers(handler,handlee);改為
          ?????call.setClientHandlers(null,null);
          ???結果程序還是拋出同樣的異常,于是意識到這可能是AXIS的一個BUG,為證明這一點,我將下面的Handler初始化代碼刪除
          ????????????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");//初始化
          ???結果還是拋出同樣的異常,果然是BUG!得到這個結論后去了apache?AXIS主頁,在問題列表中見到了完全一樣問題的提交,但沒有解答(暈!)
          ???最后得到了結論:call的setClientHandlers()方法只有當call處理簡單的數據類型,如String,int等等才能正常使用!
          ???(當然,如果你對這個問題有不同的見解,歡迎和我聯系。或許我錯了,但程序不運行是真的:))
          ???
          ??第二階段:
          ????開始在google上找問題的解決方法,這也是我的習慣:)。找了一個類似問題的討論,地址如下:
          ????http://marc.theaimsgroup.com/?l=axis-user&m=111259980822735&w=2
          ????他們的解決方法是Handler繼承于javax.xml.rpc.handler.Handler,然后在程序里動態注冊而在我的ws-axis.jar里Handler繼承于org.apache.axis.handlers.BasicHandler。當然,
          ????javax.xml.rpc.handler.Handler是org.apache.axis.handlers.BasicHandler的老爸,但在程序里老爸和兒子之間卻不能很好的兼容,這也許就是所謂的代溝??無奈中重新寫了Handler,但在運行中卻拋出異常,提示message在被invoke的時候已被更改。我靠,Handler的作用就是來更改message的啊!這是什么世道!
          ????我知道很多程序采用的就是這種方法,但我好象怎么修改都拋出上述異常。
          ????
          ??第三階段
          ?????既然在程序里動態注冊Handler行不通,于是決定寫個單獨的配置文件來注冊Handler。如果這種方法不幸失敗就返回第二階段。好馬為什么不吃回頭草??
          ??1、ws-axis.jar中修改WSClientHandler.class,修改后如下,我想你一看就明白為何修改
          ??
          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?init()?{
          ????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");
          ????}
          ??public?void?invoke(MessageContext?messageContext)?throws?AxisFault?{
          ????//do?nothing?now!
          ??}
          ??public?void?onFault(MessageContext?msgContext)?{
          ????System.out.println("處理錯誤,這里忽略!");
          ????????}
          }
          ????
          ??2、寫客戶端的配置代碼client-config.wsdd,如下:
          ???<?xml?version="1.0"?encoding="UTF-8"?>
          ???<deployment?name="defaultClientConfig"
          ??????xmlns="http://xml.apache.org/axis/wsdd/"
          ??????xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
          ???<transport?name="http"
          ???????pivot="java:org.apache.axis.transport.http.HTTPSender"/>
          ???<transport?name="local"
          ???????pivot="java:org.apache.axis.transport.local.LocalSender"/>
          ???<transport?name="java"
          ???????pivot="java:org.apache.axis.transport.java.JavaSender"/>

          <globalConfiguration>
          ??<requestFlow>
          ???<handler?type="java:com.ronghao.WSAxis.WSClientRequestHandler">
          ????<parameter?name="keyStoreFile"?value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.keystore"/>
          ????<parameter?name="keyEntryPassword"?value="changeit"/>
          ????<parameter?name="certAlias"?value="serverkey"/>
          ????<parameter?name="trustStorePassword"?value="changeit"/>
          ????<parameter?name="trustStoreFile"?value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.truststore"/>
          ????<parameter?name="keyAlias"?value="Client"/>
          ????<parameter?name="keyStorePassword"?value="changeit"/>
          ???</handler>
          ??</requestFlow>
          ??<responseFlow>
          ???<handler?type="java:com.ronghao.WSAxis.WSClientResponseHandler">
          ????<parameter?name="keyStoreFile"?value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.keystore"/>
          ????<parameter?name="keyEntryPassword"?value="changeit"/>
          ????<parameter?name="certAlias"?value="serverkey"/>
          ????<parameter?name="trustStorePassword"?value="changeit"/>
          ????<parameter?name="trustStoreFile"?value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.truststore"/>
          ????<parameter?name="keyAlias"?value="Client"/>
          ????<parameter?name="keyStorePassword"?value="changeit"/>
          ???</handler>
          ??</responseFlow>
          </globalConfiguration>
          </deployment>
          ?同樣不再解釋,不明白可以參考我的上一篇文章
          ??
          ??3、修改OrderClient.class
          ???在OrderClient.class中加入了如下代碼:
          ????EngineConfiguration?conf?=
          ???????????new?FileProvider("F:\\Tomcat\\webapps\\axis\\WEB-INF\\client-config.wsdd");//位置
          ?????Service?service?=?new?Service(conf);
          ???當然記得導入
          ???import?org.apache.axis.EngineConfiguration;
          ???import?org.apache.axis.configuration.FileProvider;
          ???
          ?運行一下,返回"ronghao",靠,搞定!
          ?注意:這次我把OrderClient.class的調用放到了一個JSP文件中而不是jbuilder中,因為有client-config.wsdd,所以你必須有完整的WEB程序發布到TOMCAT中,否則會報找不到
          相應文件。

          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=471571

          posted on 2006-11-02 13:39 SIMONE 閱讀(1373) 評論(1)  編輯  收藏 所屬分類: AXIS

          FeedBack:
          # re: AXIS服務間傳遞JavaBean及其安全解決
          2011-02-10 14:15 | haiyunit
          內容不錯,不過鄙視作者引用的話“懶惰是程序員最大的美德”,懶惰并不是程序員的美德,而是丑陋!  回復  更多評論
            
          主站蜘蛛池模板: 宣威市| 霍山县| 登封市| 河北省| 普安县| 邹城市| 车险| 建水县| 海原县| 广丰县| 五指山市| 大同县| 广昌县| 东方市| 冕宁县| 盐源县| 中方县| 格尔木市| 丰宁| 碌曲县| 秀山| 日土县| 天祝| 顺义区| 固原市| 金沙县| 昌乐县| 库伦旗| 行唐县| 大关县| 崇义县| 九寨沟县| 新昌县| 东安县| 华阴市| 浠水县| 娱乐| 邵东县| 凯里市| 汤原县| 平舆县|