JAX-WS使用Handler实现简单的WebService权限验证
WebService如果涉及到安全保密或者使用权限的时候,WS-Security通常是最优选择。WS-Security (Web服务安全)
包含了关于如何在WebService消息上保证完整性和机密性的规约,如何将签名和加密头加入SOAP消息。
不过WS-Security也有一些性能上的损耗,在信息保密要求不是很高的情况下,可以通过在SOAPHeader中添加简单的校验信息实现。
具体思路是客户端调用需要认证的服务时,在SOAPHeader中添加授权信息(如用户名、密码或者序列号等)。
服务端收到请求,在SOAPHeader中校验授权信息,校验通过则执行请求,校验不通过则返回错误提示。
客户端发起请求在SOAPHeader中添加的授权数据格式如下
- <auth xmlns="http://schemas.xmlsoap.org/soap/actor/next">
- <username>admin</username>
- <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.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<SOAPMessageContext> {
- @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<QName> 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
- <?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.server.handler.JaxServerAuthValidateHeader</javaee:handler-class>
- </javaee:handler>
- </javaee:handler-chain>
- </javaee:handler-chains>
服务端的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<SOAPMessageContext> {
- @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<QName> getHeaders() {
- return null;
- }
- }
客户端Handler配置文件handler-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.client.handler.JaxWsClientHandler</javaee:handler-class>
- </javaee:handler>
- </javaee:handler-chain>
- </javaee:handler-chains>
客户端的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 <code>features</code> 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<Handler> getHandlerChain(PortInfo portInfo) {
- List<Handler> handlerChain = new ArrayList<Handler>();
- 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;
- @Configuration
- public 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<Handler> handlers = new ArrayList<>();
- handlers.add(new JaxServerAuthValidateHeader());
- endpoint.setHandlers(handlers);
- endpoint.publish("/Sample");
- return endpoint;
- }
- }
当使用替代方式添加头部信息的时候就不需要使用 @HandlerChain 注解
JAX-WS使用Handler实现简单的WebService权限验证的更多相关文章
- 一个简单的webservice的demo(下)winform异步调用webservice
绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...
- 一个简单的Webservice的demo,简单模拟服务
前段时间一直在学习WCF,匆匆忙忙的把<WCF全面解析>和<WCF服务编程>看了一遍,好多东西都不是很懂,又听了一下WCF分布式开发的网络教程,算是马马虎虎的明白点了.回顾了一 ...
- 一个简单的webservice调用
我们先创建一个简单空web应用程序 然后添加新建项目 //我们创建一个peson对象,产生数据标识返回 using System; using System.Collections.Generic; ...
- 利用Java编写简单的WebService实例
使用Axis编写WebService比較简单,就我的理解,WebService的实现代码和编写Java代码事实上没有什么差别,主要是将哪些Java类公布为WebService. 以下是一个从编写測试样 ...
- 利用Java编写简单的WebService实例-转载
使用Axis编写WebService比较简单,就我的理解,WebService的实现代码和编写Java代码其实没有什么区别,主要是将哪些Java类发布为WebService.下面是一个从编写测试例子到 ...
- 一个简单的Webservice的demo(中)_前端页面调用
首先新建项目,这里有两种调用方式,为了能方便理解,新建页面WebserviceTest如下图: 先引用写好的服务,这里用上次写好的服务.见上次写的一个简单的Webservice的demo,简单模拟服务 ...
- 一个简单的WebService实例
WebService在.NET平台下的作用是在不同应用程序间共享数据与数据交换. 要达到这样的目标,Web services要使用两种技术: XML(标准通用标记语言下的一个子集):XML是在web上 ...
- (转)Web Service入门简介(一个简单的WebService示例)
Web Service入门简介 一.Web Service简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从I ...
- 利用VS2008发布一个简单的webservice
一个开发好的webservice,怎样发布出去,供其他电脑访问呢? 本文将介绍如何发布一个简单的webservice,其中的内容都是在网上查看别人文章,自己仿照着做了一遍,因此,难免会发生错误,如果发 ...
随机推荐
- Python验证码识别处理实例
一.准备工作与代码实例 1.PIL.pytesser.tesseract (1)安装PIL:下载地址:http://www.pythonware.com/products/pil/(CSDN下载) 下 ...
- LaTeX排版设置图表的位置 Positioning images and tables
Positioning images and tables LATEX is an editing tool that takes care of the format so you only hav ...
- Dede(织梦) CMS SQL Injection Vulnerability
测试方法: @Sebug.net dis本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负! # Dede Cms All Versions Sql Vulnerability ...
- qt study 泛型和容器
所谓泛型(generic) 能够像操作基本类型一样轻松操作对象的类和函数. qt容器类就是泛型类,基于模板的泛型类. 重载运算符overloaed operator, 托管容器 managed con ...
- Node Server零基础——开发环境文件自动重载
收录待用,修改转载已取得腾讯云授权 前言 在 web 前端开发中,我们会借助 Grunt.Gulp 和 Webpack 等工具的 Watch 模块去监听文件变化,那服务端应该怎么做?其实文件变化的监听 ...
- Hibernate之一对一关联映射
Hibernate中一对一关联映射共分为两种,一种是一对一主键关联映射,另一种是一对一唯一外键关联映射.下面简单介绍一下这两种关联映射. 一对一主键关联映射 一对一主键关联映射的两个实体有相同的ID. ...
- 引导工具GRUB详解
导读 引导程序是驻留在硬盘第一个扇区(MPR.主引导记录)的程序.GRUB是一个功能强大的多系统引导程序,专门处理Linux与其它操作系统共存的问题.下面就由我介绍一下grub.conf文件里的具体内 ...
- html5-video视频播放
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...
- java中 this和super的差别
this表示当前调用方法的对象的引用: (谁调用这种方法,谁就是这个对象,这个this就是它的引用) 比方: <pre name="code" class="jav ...
- Python 3 解析 html
资料:https://docs.python.org/3/library/html.parser.html python 自带了一个类,叫 HTMLParser. 我们用的时候需要自己定义一个类,继承 ...