本文服务端使用axis2发布web service服务,客户端采用两种方式实现:
1. 由wsdl文件生成stub客户端代码
2. 不生产stub代码,纯手工编写客户端
服务端代码如下:
1. service.xml配置文件如下,
<service name="WS"><!-- web service名称--> <description>Axis Service Description</description><!-- 接口描述--> <parameter name="ServiceClass">com.*.webservice.WSone</parameter><!-- 接口实现类--> <operation name="getPrice"><!-- 接口名称--> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> <operation name="updatePrice"><!-- 接口名称--> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> <operation name="sum"><!-- 接口名称--> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/> </operation> </service>
2. 接口实现类WSnoe代码如下,
import java.util.HashMap; import org.apache.axis2.AxisFault; public class WSone { private HashMap map = new HashMap(); public double getPrice(String symbol) throws AxisFault { LoginCheck.checkUserPwd(); // 当客户端调用getPrice方法是,在此处先进行用户名和密码校验,如果校验通过则继续后续逻辑处理,如果不通过则抛出异常。 Double price = (Double) map.get(symbol); if (price != null) { return price.doubleValue(); } return 42.00; } public void updatePrice(String symbol, double price) throws AxisFault { LoginCheck.checkUserPwd(); // 在此处先进行用户名和密码校验,如果校验通过则继续后续逻辑处理,如果不通过则抛出异常。 map.put(symbol, new Double(price)); } public int sum(int num1, int num2) throws AxisFault { LoginCheck.checkUserPwd(); // 在此处先进行用户名和密码校验,如果校验通过则继续后续逻辑处理,如果不通过则抛出异常。 return num1 + num2; } }
服务端授权认证模块类是LoginCheck,本例中用户名和密码是定死的,可根据实际情况修改,内容如下:
import java.util.Iterator; import org.apache.axiom.om.OMElement; import org.apache.axis2.AxisFault; import org.apache.axis2.context.MessageContext; public class LoginCheck { public static void checkUserPwd() throws AxisFault { MessageContext msgContext = MessageContext.getCurrentMessageContext(); Iterator list = (Iterator) msgContext.getEnvelope().getHeader().getFirstElement().getChildren(); String Username = ""; String Password = ""; while (list.hasNext()) { OMElement element = (OMElement) list.next(); if (element.getLocalName().equals("Username")) { Username = element.getText(); } if (element.getLocalName().equals("Password")) { Password = element.getText(); } } if (!Username.equals("toone") || !Password.equals("111")) { throw new AxisFault(" Authentication Fail! Check username/password "); }else{ System.out.println("use:"+Username+"验证通过"); } } }
客户端代码如下:
客户端需要将包含认证用到的用户名和密码的OMElement对象放置到soap header中。
1. 包含用户名和密码的OMElement对象HeaderOMElement代码如下,
import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.OMNamespace; public class HeaderOMElement { public static OMElement createHeaderOMElement() { OMFactory factory = OMAbstractFactory.getOMFactory(); OMNamespace SecurityElementNamespace = factory.createOMNamespace("http://handler.com", "wsse"); OMElement authenticationOM = factory.createOMElement("Authentication",SecurityElementNamespace); OMElement usernameOM = factory.createOMElement("Username",SecurityElementNamespace); OMElement passwordOM = factory.createOMElement("Password",SecurityElementNamespace); usernameOM.setText("toone"); passwordOM.setText("1111"); authenticationOM.addChild(usernameOM); authenticationOM.addChild(passwordOM); return authenticationOM; } }
2. 客户端代码实现方式1:不生成stub客户端代码
import javax.xml.namespace.QName; import org.apache.axis2.AxisFault; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.client.Options; import org.apache.axis2.rpc.client.RPCServiceClient; import com.*.testws.HeaderOMElement; public class PojoClient { public static void main(String[] args1) { String serviceName = "http://localhost:8080/TestWS/services/WS"; String namespace = "http://webservice.*.com"; String methodName = "getPrice"; Object[] methodArgs = new Object[] {}; Class[] returnTypes = new Class[] { Double.class }; try { RPCServiceClient serviceClient = new RPCServiceClient(); // 将创建的OMElement对象放置到Header中 serviceClient.addHeader(HeaderOMElement.createHeaderOMElement()); Options options = serviceClient.getOptions(); EndpointReference targetEPR = new EndpointReference(serviceName); options.setTo(targetEPR); QName op = new QName(namespace, methodName); Object[] response = serviceClient.invokeBlocking(op, methodArgs,returnTypes); Double result = (Double) response[0]; if (result == null) { System.out.println("didn't initialize!"); return; } else { System.out.println("Price ====== " + result.doubleValue()); } } catch (AxisFault e) { System.out.println("验证失败"); e.printStackTrace(); } } }
3. 客户端代码实现方式2:生成stub客户端代码
import java.rmi.RemoteException; import org.apache.axis2.AxisFault; import org.apache.axis2.client.ServiceClient; import com.*.webservice.WSStub; public class TestClient { public static void main(String[] args) { try { WSStub stub = new WSStub("http://localhost:8080/TestWS/services/WS"); ServiceClient sc = stub._getServiceClient(); sc.addHeader(HeaderOMElement.createHeaderOMElement()); stub._setServiceClient(sc); WSStub.Sum sums = new WSStub.Sum(); sums.setNum1(2); sums.setNum2(3); WSStub.SumResponse sr = stub.sum(sums); System.out.println(sr.get_return()); WSStub.GetPrice gp = new WSStub.GetPrice(); gp.setSymbol("sino"); WSStub.GetPriceResponse gpr = stub.getPrice(gp); System.out.println(gp.getSymbol()+" : "+gpr.get_return()); WSStub.UpdatePrice up = new WSStub.UpdatePrice(); up.setSymbol("sino"); up.setPrice(100.0); stub.updatePrice(up); WSStub.GetPrice gpnew = new WSStub.GetPrice(); gpnew.setSymbol("sino"); WSStub.GetPriceResponse gprnew = stub.getPrice(gpnew); System.out.println(gpnew.getSymbol()+" : "+gprnew.get_return()); } catch (AxisFault e) { System.out.println("验证失败:"+e.getMessage()); e.printStackTrace(); }catch (RemoteException e) { System.out.println("远程连接失败:"+e.getMessage()); e.printStackTrace(); } } }
以上授权实现,仅是用作授权认证机制,用户名和密码在soap消息传递过程中为明文传递,不能实现链路或信息加密。
使用TcpTrace工具进行抓包验证,参见链接:http://fxly0401.iteye.com/blog/1940119