发布目的
网上有许多有关java web service的hello world实例,有的介绍jax-ws,有的介绍框架axist、xFire、CXF等等。但是介绍向服务添加用户认证的例子并不多,至少我最近在baidu上查询有关“web service安全”、“SOAPHandler”、“web service认证”都没有找到,也许是我使用的关键字不准确,或者搜索引擎收集的信息不全面,很多信息早已经发布,可它找不出来。前几天我从《java web服务(构建与运行)》中找到了这方面的信息,发布出来,也许对一些网友有帮助,学习的同时也要学会分享。
以下使用jdk 6.0自带的jax-ws做web service
1、 定义web 服务类
//导入类或接口,略(它们都在javax包下)
@WebService
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT)
//收到请求后的处理链
@HandlerChain(file="handle-chain.xml")
//支持soap1.2
@BindingType("http://www.w3.org/2003/05/soap/bindings/HTTP/")
public class RabbitCounter {
@WebMethod
public int countRabbits(int n){
return n*4;
}
}
2、 定义处理客户端SOAP信息的handler
public class AuthValidatorHandler implements SOAPHandler<SOAPMessageContext> {
//这里省略了SOAPHandler要实现的其他方法,自行补上
//处理SOAP信息
public boolean handleMessage(SOAPMessageContext ctx) {
Boolean response_p=(Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
//如果是入站
if(!response_p){
SOAPMessage msg=ctx.getMessage();
try {
//从SOAP信息中取出认证信息
SOAPEnvelope env=msg.getSOAPPart().getEnvelope();
SOAPHeader hdr=env.getHeader();
if(hdr==null)generateSOAPFault(msg,"No message header.");
Iterator it=hdr.extractHeaderElements(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);
if(it==null||!it.hasNext())generateSOAPFault(msg,"No header block for role next.");
Node next=(Node)it.next();
String value=(next==null)?null:next.getValue();
if(value==null)generateSOAPFault(msg,"No authentication info in header block.");
String auth=value.trim();
String user=auth.split("&")[0];
String pwd=auth.split("&")[1];
return authValite(user,pwd);
} catch (SOAPException e) {
e.printStackTrace();
}
}
return false;
}
//验证用户名和密码
private boolean authValite(String user,String password){
if(user==null||password==null)return false;
//常量Constants类,略,自行补上
if(user.equals(Constants.WS_USER)&&password.equals(Constants.WS_PASSWORD)){
return true;
}else{
return false;
}
}
//生成SOAP错误
private void generateSOAPFault(SOAPMessage msg,String reason){
try {
SOAPBody body=msg.getSOAPBody();
SOAPFault fault=body.getFault();
fault.setFaultString(reason);
throw new SOAPFaultException(fault);
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3、 定义处理链(handle-chain.xml)
<?xml version="1.0" encoding="UTF-8"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>com.AuthValidatorHandler</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
4、 发布这个服务,步骤略
客户端程序
5、 编写添加认证信息的handler
public class AuthenticationHandler implements
SOAPHandler<SOAPMessageContext> {
//其它要实现的方法略
public boolean handleMessage(SOAPMessageContext ctx) {
//出站,即客户端发出请求前,添加表头信息
Boolean request_p=(Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(request_p){
try {
SOAPMessage msg=ctx.getMessage();
SOAPEnvelope env=msg.getSOAPPart().getEnvelope();
SOAPHeader hdr=env.getHeader();
if(hdr==null)hdr=env.addHeader();
//添加认证信息
QName qname_user=new QName("http://com/auth/","auth");
SOAPHeaderElement helem_user=hdr.addHeaderElement(qname_user);
helem_user.setActor(SOAPConstants.URI_SOAP_1_2_ROLE_NEXT);
//Constants常量类自行补上
helem_user.addTextNode(Constants.WS_USER+"&"+Constants.WS_PASSWORD);
msg.saveChanges();
//把SOAP消息输出到System.out,即控制台
msg.writeTo(System.out);
return true;
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
}
6、 客户端client
//通过服务wsdl文件生成客户端相关类,略
public class FibClient{
public static void main(String[] args) {
RabbitCounterService service=new RabbitCounterService();
//向SOAP添加表头
service.setHandlerResolver(new HandlerResolver(){
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerList =new ArrayList<Handler>();
//添加认证信息
handlerList.add(new AuthenticationHandler());
return handlerList;
}
});
RabbitCounter port =service.getRabbitCounterPort();
int i=port.countRabbits(5);
//得到结果
System.out.println("result:"+i);
}
}
7、 运行FibClient类,得到服务结果,如果用户名和密码不匹配,客户端会抛出错误