博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAX-WS使用Handler实现简单的WebService权限验证
阅读量:6984 次
发布时间:2019-06-27

本文共 13353 字,大约阅读时间需要 44 分钟。

  WebService如果涉及到安全保密或者使用权限的时候,WS-Security通常是最优选择。WS-Security (Web服务安全)

包含了关于如何在WebService消息上保证完整性和机密性的规约,如何将签名和加密头加入SOAP消息。
不过WS-Security也有一些性能上的损耗,在信息保密要求不是很高的情况下,可以通过在SOAPHeader中添加简单的校验信息实现。
具体思路是客户端调用需要认证的服务时,在SOAPHeader中添加授权信息(如用户名、密码或者序列号等)。
服务端收到请求,在SOAPHeader中校验授权信息,校验通过则执行请求,校验不通过则返回错误提示。

客户端发起请求在SOAPHeader中添加的授权数据格式如下

admin
admin

服务端

服务端授权校验 Handler

import java.util.Iterator;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.soap.SOAPBody;import javax.xml.soap.SOAPConstants;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;import org.apache.cxf.interceptor.Fault;import org.w3c.dom.NodeList;/** * * @author  */public class JaxServerAuthValidateHeader implements SOAPHandler
{ @Override public void close(MessageContext context) { } @Override public boolean handleFault(SOAPMessageContext context) { return true; } @Override public boolean handleMessage(SOAPMessageContext context) { // 判断消息是输入还是输出 boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); SOAPMessage soapMessage = context.getMessage(); if (!isRequest) { SOAPHeader soapHeader = null; try { SOAPEnvelope soapEnv = soapMessage.getSOAPPart().getEnvelope(); soapHeader = soapEnv.getHeader(); } catch (SOAPException e) { throw new Fault(new Exception("服务器异常!")); } if (soapHeader == null) { validateFail(soapMessage, "无 Soap Header 头信息!"); return false; } // add an node named "auth" QName qname = new QName(SOAPConstants.URI_SOAP_ACTOR_NEXT, "auth"); Iterator
iterator = soapHeader.getChildElements(qname); SOAPElement auth = null; if (iterator.hasNext()) { // 获取auth auth = (SOAPElement) iterator.next(); } // 如果授权信息元素不存在,提示错误 if (auth == null) { validateFail(soapMessage, "无授权信息!"); return false; } NodeList nameList = auth.getElementsByTagName("username"); NodeList pwdList = auth.getElementsByTagName("password"); if (nameList == null || nameList.getLength() <= 0 || pwdList == null || pwdList.getLength() <= 0) { validateFail(soapMessage, "授权信息格式错误!"); return false; } String username = nameList.item(0).getTextContent(); String password = pwdList.item(0).getTextContent(); if (!"admin".equals(username) || !"admin".equals(password)) { validateFail(soapMessage, "授权信息格式错误!"); return false; } } System.out.println(isRequest ? "服务端响应:" : "服务端接收:"); System.out.println("\r\n"); return true; } @Override public Set
getHeaders() { return null; } /** * 授权校验失败,在SOAPBody中添加SOAPFault * * @param message */ private void validateFail(SOAPMessage soapMessage, String faultString) { try { SOAPEnvelope envelop = soapMessage.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(faultString); soapMessage.saveChanges(); } catch (SOAPException e) { e.printStackTrace(); } } }

服务端Handler配置文件handler-chain.xml 

com.server.handler.JaxServerAuthValidateHeader

服务端的Service中添加Handler配置文件 

import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;import javax.xml.bind.annotation.XmlSeeAlso;import javax.xml.ws.RequestWrapper;import javax.xml.ws.ResponseWrapper;/** * This class was generated by Apache CXF 3.2.1 * 2017-12-01T14:12:00.085+08:00 * Generated source version: 3.2.1 *  */@WebService(targetNamespace = "http://tempuri.org/", name = "AExampleDemoWebService")@HandlerChain(file="handler-chain.xml")public interface AExampleDemoWebService {    @WebMethod    @WebResult(name = "single", targetNamespace = "")    public java.lang.String querySingle(        @WebParam(name = "single", targetNamespace = "http://tempuri.org/")        java.lang.String single    );    }

服务端的Service 实现类

import java.util.ArrayList;import java.util.List;import cn.evun.iwm.receive.soap.service.AExampleDemoWebService;import cn.evun.iwm.receive.soap.struc.sample.InputParam;import cn.evun.iwm.receive.soap.struc.sample.OutputParam;@javax.jws.WebService(serviceName = "aexampleDemoWebService", portName = "Sample",     targetNamespace = "http://tempuri.org/", endpointInterface = "cn.soap.service.AExampleDemoWebService")public class AExampleDemoWebServiceImpl implements AExampleDemoWebService {    @Override    public String querySingle(String input) {        return "success";    }}

客户端

客户端添加授权Handler

import java.io.IOException;import java.util.Set;import javax.xml.namespace.QName;import javax.xml.soap.SOAPConstants;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;public class JaxWsClientHandler implements SOAPHandler
{ @Override public boolean handleMessage(SOAPMessageContext context) { // 判断消息是请求还是响应 Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); SOAPMessage soapMessage = context.getMessage(); if (isRequest) { try { SOAPHeader soapHeader = soapMessage.getSOAPHeader(); if (soapHeader == null) { soapHeader = soapMessage.getSOAPPart().getEnvelope().addHeader(); } // add an node named "auth" QName qname = new QName(SOAPConstants.URI_SOAP_ACTOR_NEXT, "auth"); SOAPElement auth = soapHeader.addChildElement(qname); SOAPElement name = auth.addChildElement("username"); name.addTextNode("admin"); SOAPElement password = auth.addChildElement("password"); password.addTextNode("admin"); soapMessage.saveChanges(); // tracking soapMessage.writeTo(System.out); } catch (SOAPException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); } } return true; } @Override public boolean handleFault(SOAPMessageContext context) { return false; } @Override public void close(MessageContext context) { } @Override public Set
getHeaders() { return null; }}

客户端Handler配置文件handler-chain.xml

com.client.handler.JaxWsClientHandler

客户端的Service中添加Handler配置文件

import java.net.MalformedURLException;import java.net.URL;import javax.xml.namespace.QName;import javax.xml.ws.WebEndpoint;import javax.xml.ws.WebServiceClient;import javax.xml.ws.WebServiceFeature;import javax.xml.ws.Service;/** * This class was generated by Apache CXF 3.2.1 * 2017-12-01T14:12:00.117+08:00 * Generated source version: 3.2.1 *  */@WebServiceClient(name = "aexampleDemoWebService",                   wsdlLocation = "http://localhost:8090/service/Sample?wsdl",                  targetNamespace = "http://tempuri.org/") @HandlerChain(file="handler-chain.xml")  public class AexampleDemoWebServiceSoap extends Service {    public final static URL WSDL_LOCATION;    public final static QName SERVICE = new QName("http://tempuri.org/", "aexampleDemoWebService");    public final static QName Sample = new QName("http://tempuri.org/", "Sample");    static {        URL url = null;        try {            url = new URL("http://localhost:8090/service/Sample?wsdl");        } catch (MalformedURLException e) {            java.util.logging.Logger.getLogger(AexampleDemoWebServiceSoap.class.getName())                .log(java.util.logging.Level.INFO,                      "Can not initialize the default wsdl from {0}", "http://localhost:8090/service/Sample?wsdl");        }        WSDL_LOCATION = url;    }    public AexampleDemoWebServiceSoap(URL wsdlLocation) {        super(wsdlLocation, SERVICE);    }    public AexampleDemoWebServiceSoap(URL wsdlLocation, QName serviceName) {        super(wsdlLocation, serviceName);    }    public AexampleDemoWebServiceSoap() {        super(WSDL_LOCATION, SERVICE);    }        public AexampleDemoWebServiceSoap(WebServiceFeature ... features) {        super(WSDL_LOCATION, SERVICE, features);    }    public AexampleDemoWebServiceSoap(URL wsdlLocation, WebServiceFeature ... features) {        super(wsdlLocation, SERVICE, features);    }    public AexampleDemoWebServiceSoap(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {        super(wsdlLocation, serviceName, features);    }        /**     *     * @return     *     returns AExampleDemoWebService     */    @WebEndpoint(name = "Sample")    public AExampleDemoWebService getSample() {        return super.getPort(Sample, AExampleDemoWebService.class);    }    /**     *      * @param features     *     A list of {
@link javax.xml.ws.WebServiceFeature} to configure on the proxy.    *   Supported features not in the features parameter will have their default values. * @return * returns AExampleDemoWebService */ @WebEndpoint(name = "Sample") public AExampleDemoWebService getSample(WebServiceFeature... features) { return super.getPort(Sample, AExampleDemoWebService.class, features); }}

客户端发起请求

QName SERVICE_NAME = new QName("http://tempuri.org/", "aexampleDemoWebService");URL url = new URL("http://localhost:8090/service/Sample?wsdl");AexampleDemoWebServiceSoap ss = new AexampleDemoWebServiceSoap(wsdlURL, SERVICE_NAME);AExampleDemoWebService port = ss.getSample();port.querySingle("1111");

@HandlerChain 注解 替代方式

  客户端  通过 HandlerReolver 代替 @HandlerChain 注解 导入 Handler 配置文件

  handler-chain配置文件对所有的请求都添加授权验证信息,有些时候不是所有的请求都需要添加授权验证,HandlerResolver提供了在编程时添加Handler的方法,可以用HandlerResolver给需要授权的接口添加Handler。

QName SERVICE_NAME = new QName("http://tempuri.org/", "aexampleDemoWebService");URL url = new URL("http://localhost:8090/service/Sample?wsdl");AexampleDemoWebServiceSoap ss = new AexampleDemoWebServiceSoap(wsdlURL, SERVICE_NAME);//通过HandlerResolver添加Handler  ss.setHandlerResolver(new HandlerResolver(){        @Override      @SuppressWarnings("rawtypes")                 public List
getHandlerChain(PortInfo portInfo) { List
handlerChain = new ArrayList
(); handlerChain.add(new JaxWsClientHandler()); return handlerChain; } });AExampleDemoWebService port = ss.getSample();port.querySingle("2222");

服务端 @HandlerChain 注解替代 

  服务发布时服务端通过继承至 Endpoint 实现类 EndpointImpl 的 setHandlers 方法添加头部信息 代替 @HandlerChain 注解 导入 Handler 配置文件

import java.util.ArrayList;import java.util.List;import javax.xml.ws.Endpoint;import javax.xml.ws.handler.Handler;import org.apache.cxf.Bus;import org.apache.cxf.bus.spring.SpringBus;import org.apache.cxf.interceptor.Interceptor;import org.apache.cxf.jaxws.EndpointImpl;import org.apache.cxf.message.Message;import org.apache.cxf.transport.servlet.CXFServlet;import org.springframework.boot.context.embedded.ServletRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class CXFConfig {    @Bean    public ServletRegistrationBean dispatcherServlet() {        return new ServletRegistrationBean(new CXFServlet(), "/service/*");    }    @Bean(name = Bus.DEFAULT_BUS_ID)    public SpringBus springBus() {        return new SpringBus();    }    @Bean    public AExampleDemoWebServiceImpl aExampleDemoWebServiceImpl() {        return new AExampleDemoWebServiceImpl();    }    @Bean    public Endpoint endpointWebServiceSampleImpl() {                EndpointImpl endpoint = new EndpointImpl(springBus(), aExampleDemoWebServiceImpl());        // SOAPHandler 方式         @SuppressWarnings("rawtypes")        List
handlers = new ArrayList<>(); handlers.add(new JaxServerAuthValidateHeader()); endpoint.setHandlers(handlers); endpoint.publish("/Sample"); return endpoint; }}

当使用替代方式添加头部信息的时候就不需要使用 @HandlerChain 注解 

转载地址:http://adtpl.baihongyu.com/

你可能感兴趣的文章
C语言的预处理、编译、汇编、链接
查看>>
nginx的启动、停止、平滑重启
查看>>
(转)ASIHTTPRequest 详解, http 请求终结者
查看>>
编辑器实时保存内容
查看>>
COMPUTER HARDWARE OPENCART 主题模板 ABC-0059
查看>>
android listview item点击时更改textview的颜色 代码中实现
查看>>
How to install Docker on Ubuntu
查看>>
EXTjs
查看>>
开启win7 FTP 服务 无法登陆的原因
查看>>
SSO之CAS单点登录详细搭建
查看>>
开发自定义JSF组件(4) 保存状态与恢复状态
查看>>
ZBarSDK扫描二维码
查看>>
Windows的Win键被自动按下解决方案
查看>>
lucene4.7 分页(五)
查看>>
MyEclipse_15字体设置
查看>>
PHP中处理函数的函数(Function Handling Functions)
查看>>
href="#"与javascript:void(0)的区别
查看>>
web端即时通讯
查看>>
Python xlrd 读取xls文件
查看>>
Netflix Zuul与Nginx的性能对比
查看>>