在AXIS服務(wù)間傳遞JavaBean及其安全解決
?這是AXIS學(xué)習(xí)筆記的最后一篇。在前面我們討論了最簡單的HelloWorld服務(wù),客戶端并沒有向服務(wù)器端
?傳遞參數(shù),現(xiàn)在我們來傳傳JavaBean。當然,也可以傳遞你自己定義的JAVA類,但那樣你必須自己創(chuàng)建
?專門的XML序列化器和反序列化器;而對JavaBean,AXIS提供了現(xiàn)成的序列化器。(有人說:懶惰是程序員最大的美德,我喜歡,所以我就傳傳JavaBean)
?
?一、服務(wù)器端
??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、修改服務(wù)器端配置文件server-config.wsdd
???在server-config.wsdd中相應(yīng)位置添加以下代碼
??<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>
??可以看到和前面的發(fā)布服務(wù)代碼相比僅多了一行代碼
????<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";??//服務(wù)所在位置
????????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));
????????????//調(diào)用的服務(wù)器端方法
????????????call.setOperationName(new?QName("Order",?"returnOrder"));
????????????//設(shè)定傳入的參數(shù),這里qn即Order.class
????????????call.addParameter("arg1",?qn,?ParameterMode.IN);
????????????//設(shè)定返回的參數(shù)是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"。
??
??和上一篇文章一樣,我們不容許在網(wǎng)絡(luò)中傳遞XML是明文,于是需要加密和驗證。這里我們繼續(xù)采用上次所講的框架。(已打包成ws-axis.jar)
??
?一、修改服務(wù)器端配置文件server-config.wsdd(和上一文章一模一樣!不再羅嗦)
??在server-config.wsdd中相應(yīng)位置添加以下代碼
?????????<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>
????????
?二、客戶端(區(qū)別就在這里,注意!!)
??首先在這里要說一下,客戶端代碼編寫困擾了我很長一段時間(整整一天),因為它并不象我想象的那么簡單,當然解決起來還是挺簡單的:)問題的解決經(jīng)歷了三個階段
??
??第一階段:
???在這個階段我想當然的在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
???這個方法也是我在上一文章里介紹的,結(jié)果拋出以下異常:
???faultString:?org.xml.sax.SAXException:?Deserializing?parameter
????'newProfileReturn':??could?not?find?deserializer?for?type
???{urn:BeanService?Order}SerializableProfile
???也就是說不能正常解析XML文件,于是理所當然的郁悶了,覺得代碼中肯定漏設(shè)了CALL的一個屬性,于是查看AXIS的源代碼,沒有結(jié)果!轉(zhuǎn)機出現(xiàn)在下面一行代碼,在不斷的拋出異常中我修改了代碼
???將call.setClientHandlers(handler,handlee);改為
?????call.setClientHandlers(null,null);
???結(jié)果程序還是拋出同樣的異常,于是意識到這可能是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");//初始化
???結(jié)果還是拋出同樣的異常,果然是BUG!得到這個結(jié)論后去了apache?AXIS主頁,在問題列表中見到了完全一樣問題的提交,但沒有解答(暈!)
???最后得到了結(jié)論:call的setClientHandlers()方法只有當call處理簡單的數(shù)據(jù)類型,如String,int等等才能正常使用!
???(當然,如果你對這個問題有不同的見解,歡迎和我聯(lián)系。或許我錯了,但程序不運行是真的:))
???
??第二階段:
????開始在google上找問題的解決方法,這也是我的習(xí)慣:)。找了一個類似問題的討論,地址如下:
????http://marc.theaimsgroup.com/?l=axis-user&m=111259980822735&w=2
????他們的解決方法是Handler繼承于javax.xml.rpc.handler.Handler,然后在程序里動態(tài)注冊而在我的ws-axis.jar里Handler繼承于org.apache.axis.handlers.BasicHandler。當然,
????javax.xml.rpc.handler.Handler是org.apache.axis.handlers.BasicHandler的老爸,但在程序里老爸和兒子之間卻不能很好的兼容,這也許就是所謂的代溝??無奈中重新寫了Handler,但在運行中卻拋出異常,提示message在被invoke的時候已被更改。我靠,Handler的作用就是來更改message的啊!這是什么世道!
????我知道很多程序采用的就是這種方法,但我好象怎么修改都拋出上述異常。
????
??第三階段
?????既然在程序里動態(tài)注冊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);
???當然記得導(dǎo)入
???import?org.apache.axis.EngineConfiguration;
???import?org.apache.axis.configuration.FileProvider;
???
?運行一下,返回"ronghao",靠,搞定!
?注意:這次我把OrderClient.class的調(diào)用放到了一個JSP文件中而不是jbuilder中,因為有client-config.wsdd,所以你必須有完整的WEB程序發(fā)布到TOMCAT中,否則會報找不到
相應(yīng)文件。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=471571
posted on 2006-11-02 13:39
SIMONE 閱讀(1369)
評論(1) 編輯 收藏 所屬分類:
AXIS