本文服务端使用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