WebService如果涉及到安全保密或者使用权限的时候,WS-Security通常是最优选择。WS-Security (Web服务安全) 包含了关于如何在WebService消息上保证完整性和机密性的规约,如何将签名和加密头加入SOAP消息。不过WS-Security也有一些性能上的损耗,在信息保密要求不是很高的情况下,可以通过在SOAPHeader中添加简单的校验信息实现。
具体思路是客户端调用需要认证的服务时,在SOAPHeader中添加授权信息(如用户名、密码或者序列号等)。服务端收到请求,在SOAPHeader中校验授权信息,校验通过则执行请求,校验不通过则返回错误提示。
实例代码
http://download.csdn.net/detail/accountwcx/8922191
客户端发起请求在SOAPHeader中添加的授权数据格式如下
<auth xmlns="http://www.tmp.com/auth"> <name>admin</name> <password>admin</password> </auth>
服务端授权校验Handler
import java.util.Iterator;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
* 服务端请求校验Handler
* @author accountwcx@qq.com
*
*/
public class ValidateAuthHandler implements SOAPHandler<SOAPMessageContext> {
@Override
public void close(MessageContext context) {
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
// 判断消息是请求还是响应
Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
boolean result = false;
SOAPMessage message = context.getMessage();
//如果是请求,则执行校验
if(!output){
result = validate(message);
if(!result){
validateFail(message);
}
}
System.out.println(output ? "服务端响应:" : "服务端接收:");
try {
message.writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("\r\n");
return result;
}
/**
* 授权校验失败,在SOAPBody中添加SOAPFault
* @param message
*/
private void validateFail(SOAPMessage message) {
try {
SOAPEnvelope envelop = message.getSOAPPart().getEnvelope();
envelop.getHeader().detachNode();
envelop.addHeader();
envelop.getBody().detachNode();
SOAPBody body = envelop.addBody();
SOAPFault fault = body.getFault();
if (fault == null) {
fault = body.addFault();
}
fault.setFaultString("授权校验失败!");
message.saveChanges();
} catch (SOAPException e) {
e.printStackTrace();
}
}
/**
* 授权校验
* @param message
* @return 校验成功返回true,校验失败返回false
*/
private boolean validate(SOAPMessage message){
boolean result = false;
try {
SOAPEnvelope envelop = message.getSOAPPart().getEnvelope();
SOAPHeader header = envelop.getHeader();
if(header != null){
Iterator iterator = header.getChildElements(new QName("http://www.tmp.com/auth", "auth"));
SOAPElement auth = null;
if(iterator.hasNext()){
//获取auth
auth = (SOAPElement)iterator.next();
//获取name
Iterator it = auth.getChildElements(new QName("http://www.tmp.com/auth", "name"));
SOAPElement name = null;
if(it.hasNext()){
name = (SOAPElement)it.next();
}
//获取password
it = auth.getChildElements(new QName("http://www.tmp.com/auth", "password"));
SOAPElement password = null;
if(it.hasNext()){
password = (SOAPElement)it.next();
}
//判断name和password是否符合要求
if(name != null && password != null && "admin".equals(name.getValue()) && "admin".equals(password.getValue())){
result = true;
}
}
}
} catch (SOAPException e) {
e.printStackTrace();
}
return result;
}
@Override
public Set<QName> getHeaders() {
return null;
}
}
客户端添加授权Handler
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
* 客户端添加请求授权
* @author accountwcx@qq.com
*
*/
public class AddAuthHandler implements SOAPHandler<SOAPMessageContext> {
@Override
public boolean handleMessage(SOAPMessageContext context) {
// 判断消息是请求还是响应
Boolean output = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
SOAPMessage message = context.getMessage();
if (output) {
try {
SOAPHeader header = message.getSOAPHeader();
if (header == null) {
header = message.getSOAPPart().getEnvelope().addHeader();
}
SOAPElement auth = header.addChildElement(new QName("http://www.tmp.com/auth", "auth"));
SOAPElement name = auth.addChildElement("name");
name.addTextNode("admin");
SOAPElement password = auth.addChildElement("password");
password.addTextNode("admin");
message.saveChanges();
} catch (SOAPException e) {
e.printStackTrace();
}
}
System.out.println(output ? "客户端请求:" : "客户端接收:");
try {
message.writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("\r\n");
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
@Override
public void close(MessageContext context) {
}
@Override
public Set<QName> getHeaders() {
return null;
}
}<?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.rvho.client.handler.AddAuthHandler</javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains>
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.9-b130926.1035
* Generated source version: 2.2
*
*/
@WebServiceClient(name = "HelloWSService", targetNamespace = "http://www.tmp.com/ws/hello", wsdlLocation = "http://localhost:8014/jaxwsserver/services/hello?wsdl")
@HandlerChain(file="handler-chain.xml")
public class HelloWSService
extends Service
{
private final static URL HELLOWSSERVICE_WSDL_LOCATION;
private final static WebServiceException HELLOWSSERVICE_EXCEPTION;
private final static QName HELLOWSSERVICE_QNAME = new QName("http://www.tmp.com/ws/hello", "HelloWSService");
static {
URL url = null;
WebServiceException e = null;
try {
url = new URL("http://localhost:8014/jaxwsserver/services/hello?wsdl");
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
HELLOWSSERVICE_WSDL_LOCATION = url;
HELLOWSSERVICE_EXCEPTION = e;
}
public HelloWSService() {
super(__getWsdlLocation(), HELLOWSSERVICE_QNAME);
}
public HelloWSService(WebServiceFeature... features) {
super(__getWsdlLocation(), HELLOWSSERVICE_QNAME, features);
}
public HelloWSService(URL wsdlLocation) {
super(wsdlLocation, HELLOWSSERVICE_QNAME);
}
public HelloWSService(URL wsdlLocation, WebServiceFeature... features) {
super(wsdlLocation, HELLOWSSERVICE_QNAME, features);
}
public HelloWSService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public HelloWSService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
super(wsdlLocation, serviceName, features);
}
/**
*
* @return
* returns HelloWS
*/
@WebEndpoint(name = "HelloWSPort")
public HelloWS getHelloWSPort() {
return super.getPort(new QName("http://www.tmp.com/ws/hello", "HelloWSPort"), HelloWS.class);
}
/**
*
* @param features
* A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
* @return
* returns HelloWS
*/
@WebEndpoint(name = "HelloWSPort")
public HelloWS getHelloWSPort(WebServiceFeature... features) {
return super.getPort(new QName("http://www.tmp.com/ws/hello", "HelloWSPort"), HelloWS.class, features);
}
private static URL __getWsdlLocation() {
if (HELLOWSSERVICE_EXCEPTION!= null) {
throw HELLOWSSERVICE_EXCEPTION;
}
return HELLOWSSERVICE_WSDL_LOCATION;
}
}
URL wsdlUrl = new URL("http://localhost:7180/jaxwsserver/services/hello?wsdl");
HelloWSService helloWSS = new HelloWSService(wsdlUrl);
HelloWS helloWS = helloWSS.getHelloWSPort();
String index = helloWS.index();<!-- 客户端请求 --> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <auth xmlns="http://www.tmp.com/auth"> <name>admin</name> <password>admin</password> </auth> </SOAP-ENV:Header> <S:Body> <ns2:index xmlns:ns2="http://www.tmp.com/ws/hello" /> </S:Body> </S:Envelope> <!-- 服务端响应 --> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <S:Body> <ns2:indexResponse xmlns:ns2="http://www.tmp.com/ws/hello"> <return>hello</return> </ns2:indexResponse> </S:Body> </S:Envelope>
<!-- 客户端请求 --> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <auth xmlns="http://www.tmp.com/auth"> <name></name> <password></password> </auth> </SOAP-ENV:Header> <S:Body> <ns2:index xmlns:ns2="http://www.tmp.com/ws/hello" /> </S:Body> </S:Envelope> <!-- 服务器响应 --> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <S:Header/> <S:Body> <S:Fault> <faultcode>S:Server</faultcode> <faultstring>授权校验失败!</faultstring> </S:Fault> </S:Body> </S:Envelope>
handler-chain配置文件对所有的请求都添加授权验证信息,有些时候不是所有的请求都需要添加授权验证,HandlerResolver提供了在编程时添加Handler的方法,可以用HandlerResolver给需要授权的接口添加Handler。
URL wsdlUrl = new URL("http://localhost:7180/jaxwsserver/services/hello?wsdl");
HelloWSService helloWSS = new HelloWSService(wsdlUrl);
//通过HandlerResolver添加Handler
helloWSS.setHandlerResolver(new HandlerResolver(){
@Override
@SuppressWarnings("rawtypes")
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(new AddAuthHandler());
return handlerChain;
}
});
HelloWS helloWS = helloWSS.getHelloWSPort();
//调用index服务
String index = helloWS.index();版权声明:本文为博主原创文章,未经博主允许不得转载。
JAX-WS使用Handler实现简单的WebService权限验证
原文:http://blog.csdn.net/accountwcx/article/details/47000531