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

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

  1. <auth xmlns="http://schemas.xmlsoap.org/soap/actor/next">
  2. <username>admin</username>
  3. <password>admin</password>
  4. </auth>

服务端

服务端授权校验 Handler

  1. import java.util.Iterator;
  2. import java.util.Set;
  3.  
  4. import javax.xml.namespace.QName;
  5. import javax.xml.soap.SOAPBody;
  6. import javax.xml.soap.SOAPConstants;
  7. import javax.xml.soap.SOAPElement;
  8. import javax.xml.soap.SOAPEnvelope;
  9. import javax.xml.soap.SOAPException;
  10. import javax.xml.soap.SOAPFault;
  11. import javax.xml.soap.SOAPHeader;
  12. import javax.xml.soap.SOAPMessage;
  13. import javax.xml.ws.handler.MessageContext;
  14. import javax.xml.ws.handler.soap.SOAPHandler;
  15. import javax.xml.ws.handler.soap.SOAPMessageContext;
  16.  
  17. import org.apache.cxf.interceptor.Fault;
  18. import org.w3c.dom.NodeList;
  19.  
  20. /**
  21. *
  22. * @author
  23. */
  24. public class JaxServerAuthValidateHeader implements SOAPHandler<SOAPMessageContext> {
  25.  
  26. @Override
  27. public void close(MessageContext context) {
  28. }
  29.  
  30. @Override
  31. public boolean handleFault(SOAPMessageContext context) {
  32. return true;
  33. }
  34.  
  35. @Override
  36. public boolean handleMessage(SOAPMessageContext context) {
  37.  
  38. // 判断消息是输入还是输出
  39. boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  40. SOAPMessage soapMessage = context.getMessage();
  41.  
  42. if (!isRequest) {
  43.  
  44. SOAPHeader soapHeader = null;
  45.  
  46. try {
  47. SOAPEnvelope soapEnv = soapMessage.getSOAPPart().getEnvelope();
  48. soapHeader = soapEnv.getHeader();
  49. } catch (SOAPException e) {
  50. throw new Fault(new Exception("服务器异常!"));
  51. }
  52.  
  53. if (soapHeader == null) {
  54. validateFail(soapMessage, "无 Soap Header 头信息!");
  55. return false;
  56. }
  57.  
  58. // add an node named "auth"
  59. QName qname = new QName(SOAPConstants.URI_SOAP_ACTOR_NEXT, "auth");
  60. Iterator<?> iterator = soapHeader.getChildElements(qname);
  61. SOAPElement auth = null;
  62. if (iterator.hasNext()) {
  63. // 获取auth
  64. auth = (SOAPElement) iterator.next();
  65. }
  66.  
  67. // 如果授权信息元素不存在,提示错误
  68. if (auth == null) {
  69. validateFail(soapMessage, "无授权信息!");
  70. return false;
  71. }
  72.  
  73. NodeList nameList = auth.getElementsByTagName("username");
  74. NodeList pwdList = auth.getElementsByTagName("password");
  75. if (nameList == null || nameList.getLength() <= 0 || pwdList == null || pwdList.getLength() <= 0) {
  76. validateFail(soapMessage, "授权信息格式错误!");
  77. return false;
  78. }
  79.  
  80. String username = nameList.item(0).getTextContent();
  81. String password = pwdList.item(0).getTextContent();
  82. if (!"admin".equals(username) || !"admin".equals(password)) {
  83. validateFail(soapMessage, "授权信息格式错误!");
  84. return false;
  85. }
  86.  
  87. }
  88.  
  89. System.out.println(isRequest ? "服务端响应:" : "服务端接收:");
  90. System.out.println("\r\n");
  91.  
  92. return true;
  93.  
  94. }
  95.  
  96. @Override
  97. public Set<QName> getHeaders() {
  98. return null;
  99. }
  100.  
  101. /**
  102. * 授权校验失败,在SOAPBody中添加SOAPFault
  103. *
  104. * @param message
  105. */
  106. private void validateFail(SOAPMessage soapMessage, String faultString) {
  107. try {
  108.  
  109. SOAPEnvelope envelop = soapMessage.getSOAPPart().getEnvelope();
  110.  
  111. envelop.getHeader().detachNode();
  112. envelop.addHeader();
  113.  
  114. envelop.getBody().detachNode();
  115. SOAPBody body = envelop.addBody();
  116.  
  117. SOAPFault fault = body.getFault();
  118.  
  119. if (fault == null) {
  120. fault = body.addFault();
  121. }
  122.  
  123. fault.setFaultString(faultString);
  124.  
  125. soapMessage.saveChanges();
  126.  
  127. } catch (SOAPException e) {
  128. e.printStackTrace();
  129. }
  130. }
  131.  
  132. }

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
  3. xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  4. <javaee:handler-chain>
  5. <javaee:handler>
  6. <javaee:handler-class>com.server.handler.JaxServerAuthValidateHeader</javaee:handler-class>
  7. </javaee:handler>
  8. </javaee:handler-chain>
  9. </javaee:handler-chains>

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

  1. import javax.jws.WebMethod;
  2. import javax.jws.WebParam;
  3. import javax.jws.WebResult;
  4. import javax.jws.WebService;
  5. import javax.xml.bind.annotation.XmlSeeAlso;
  6. import javax.xml.ws.RequestWrapper;
  7. import javax.xml.ws.ResponseWrapper;
  8.  
  9. /**
  10. * This class was generated by Apache CXF 3.2.1
  11. * 2017-12-01T14:12:00.085+08:00
  12. * Generated source version: 3.2.1
  13. *
  14. */
  15. @WebService(targetNamespace = "http://tempuri.org/", name = "AExampleDemoWebService")
  16. @HandlerChain(file="handler-chain.xml")
  17. public interface AExampleDemoWebService {
  18.  
  19. @WebMethod
  20. @WebResult(name = "single", targetNamespace = "")
  21. public java.lang.String querySingle(
  22. @WebParam(name = "single", targetNamespace = "http://tempuri.org/")
  23. java.lang.String single
  24. );
  25.  
  26. }

服务端的Service 实现类

  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. import cn.evun.iwm.receive.soap.service.AExampleDemoWebService;
  5. import cn.evun.iwm.receive.soap.struc.sample.InputParam;
  6. import cn.evun.iwm.receive.soap.struc.sample.OutputParam;
  7.  
  8. @javax.jws.WebService(serviceName = "aexampleDemoWebService", portName = "Sample",
  9. targetNamespace = "http://tempuri.org/", endpointInterface = "cn.soap.service.AExampleDemoWebService")
  10. public class AExampleDemoWebServiceImpl implements AExampleDemoWebService {
  11.  
  12. @Override
  13. public String querySingle(String input) {
  14. return "success";
  15. }
  16.  
  17. }

客户端

客户端添加授权Handler

  1. import java.io.IOException;
  2. import java.util.Set;
  3.  
  4. import javax.xml.namespace.QName;
  5. import javax.xml.soap.SOAPConstants;
  6. import javax.xml.soap.SOAPElement;
  7. import javax.xml.soap.SOAPException;
  8. import javax.xml.soap.SOAPHeader;
  9. import javax.xml.soap.SOAPMessage;
  10. import javax.xml.ws.handler.MessageContext;
  11. import javax.xml.ws.handler.soap.SOAPHandler;
  12. import javax.xml.ws.handler.soap.SOAPMessageContext;
  13.  
  14. public class JaxWsClientHandler implements SOAPHandler<SOAPMessageContext> {
  15.  
  16. @Override
  17. public boolean handleMessage(SOAPMessageContext context) {
  18.  
  19. // 判断消息是请求还是响应
  20. Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  21. SOAPMessage soapMessage = context.getMessage();
  22.  
  23. if (isRequest) {
  24.  
  25. try {
  26.  
  27. SOAPHeader soapHeader = soapMessage.getSOAPHeader();
  28. if (soapHeader == null) {
  29. soapHeader = soapMessage.getSOAPPart().getEnvelope().addHeader();
  30. }
  31.  
  32. // add an node named "auth"
  33. QName qname = new QName(SOAPConstants.URI_SOAP_ACTOR_NEXT, "auth");
  34. SOAPElement auth = soapHeader.addChildElement(qname);
  35.  
  36. SOAPElement name = auth.addChildElement("username");
  37. name.addTextNode("admin");
  38.  
  39. SOAPElement password = auth.addChildElement("password");
  40. password.addTextNode("admin");
  41.  
  42. soapMessage.saveChanges();
  43.  
  44. // tracking
  45. soapMessage.writeTo(System.out);
  46.  
  47. } catch (SOAPException e) {
  48. System.err.println(e);
  49. } catch (IOException e) {
  50. System.err.println(e);
  51. }
  52.  
  53. }
  54.  
  55. return true;
  56.  
  57. }
  58.  
  59. @Override
  60. public boolean handleFault(SOAPMessageContext context) {
  61. return false;
  62. }
  63.  
  64. @Override
  65. public void close(MessageContext context) {
  66.  
  67. }
  68.  
  69. @Override
  70. public Set<QName> getHeaders() {
  71. return null;
  72. }
  73.  
  74. }

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
  3. xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  4. <javaee:handler-chain>
  5. <javaee:handler>
  6. <javaee:handler-class>com.client.handler.JaxWsClientHandler</javaee:handler-class>
  7. </javaee:handler>
  8. </javaee:handler-chain>
  9. </javaee:handler-chains>

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

  1. import java.net.MalformedURLException;
  2. import java.net.URL;
  3. import javax.xml.namespace.QName;
  4. import javax.xml.ws.WebEndpoint;
  5. import javax.xml.ws.WebServiceClient;
  6. import javax.xml.ws.WebServiceFeature;
  7.  
  8. import javax.xml.ws.Service;
  9.  
  10. /**
  11. * This class was generated by Apache CXF 3.2.1
  12. * 2017-12-01T14:12:00.117+08:00
  13. * Generated source version: 3.2.1
  14. *
  15. */
  16. @WebServiceClient(name = "aexampleDemoWebService",
  17. wsdlLocation = "http://localhost:8090/service/Sample?wsdl",
  18. targetNamespace = "http://tempuri.org/")
  19. @HandlerChain(file="handler-chain.xml")
  20. public class AexampleDemoWebServiceSoap extends Service {
  21.  
  22. public final static URL WSDL_LOCATION;
  23.  
  24. public final static QName SERVICE = new QName("http://tempuri.org/", "aexampleDemoWebService");
  25. public final static QName Sample = new QName("http://tempuri.org/", "Sample");
  26. static {
  27. URL url = null;
  28. try {
  29. url = new URL("http://localhost:8090/service/Sample?wsdl");
  30. } catch (MalformedURLException e) {
  31. java.util.logging.Logger.getLogger(AexampleDemoWebServiceSoap.class.getName())
  32. .log(java.util.logging.Level.INFO,
  33. "Can not initialize the default wsdl from {0}", "http://localhost:8090/service/Sample?wsdl");
  34. }
  35. WSDL_LOCATION = url;
  36. }
  37.  
  38. public AexampleDemoWebServiceSoap(URL wsdlLocation) {
  39. super(wsdlLocation, SERVICE);
  40. }
  41.  
  42. public AexampleDemoWebServiceSoap(URL wsdlLocation, QName serviceName) {
  43. super(wsdlLocation, serviceName);
  44. }
  45.  
  46. public AexampleDemoWebServiceSoap() {
  47. super(WSDL_LOCATION, SERVICE);
  48. }
  49.  
  50. public AexampleDemoWebServiceSoap(WebServiceFeature ... features) {
  51. super(WSDL_LOCATION, SERVICE, features);
  52. }
  53.  
  54. public AexampleDemoWebServiceSoap(URL wsdlLocation, WebServiceFeature ... features) {
  55. super(wsdlLocation, SERVICE, features);
  56. }
  57.  
  58. public AexampleDemoWebServiceSoap(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {
  59. super(wsdlLocation, serviceName, features);
  60. }
  61.  
  62. /**
  63. *
  64. * @return
  65. * returns AExampleDemoWebService
  66. */
  67. @WebEndpoint(name = "Sample")
  68. public AExampleDemoWebService getSample() {
  69. return super.getPort(Sample, AExampleDemoWebService.class);
  70. }
  71.  
  72. /**
  73. *
  74. * @param features
  75. * 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.
  76. * @return
  77. * returns AExampleDemoWebService
  78. */
  79. @WebEndpoint(name = "Sample")
  80. public AExampleDemoWebService getSample(WebServiceFeature... features) {
  81. return super.getPort(Sample, AExampleDemoWebService.class, features);
  82. }
  83.  
  84. }

客户端发起请求

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

@HandlerChain 注解 替代方式

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

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

  1. QName SERVICE_NAME = new QName("http://tempuri.org/", "aexampleDemoWebService");
  2. URL url = new URL("http://localhost:8090/service/Sample?wsdl");
  3. AexampleDemoWebServiceSoap ss = new AexampleDemoWebServiceSoap(wsdlURL, SERVICE_NAME);
  4. //通过HandlerResolver添加Handler
  5. ss.setHandlerResolver(new HandlerResolver(){
  6.  
  7. @Override
  8. @SuppressWarnings("rawtypes")
  9. public List<Handler> getHandlerChain(PortInfo portInfo) {
  10. List<Handler> handlerChain = new ArrayList<Handler>();
  11. handlerChain.add(new JaxWsClientHandler());
  12. return handlerChain;
  13. }
  14.  
  15. });
  16. AExampleDemoWebService port = ss.getSample();
  17. port.querySingle("2222");

服务端 @HandlerChain 注解替代 

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

  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. import javax.xml.ws.Endpoint;
  5. import javax.xml.ws.handler.Handler;
  6.  
  7. import org.apache.cxf.Bus;
  8. import org.apache.cxf.bus.spring.SpringBus;
  9. import org.apache.cxf.interceptor.Interceptor;
  10. import org.apache.cxf.jaxws.EndpointImpl;
  11. import org.apache.cxf.message.Message;
  12. import org.apache.cxf.transport.servlet.CXFServlet;
  13. import org.springframework.boot.context.embedded.ServletRegistrationBean;
  14. import org.springframework.context.annotation.Bean;
  15. import org.springframework.context.annotation.Configuration;
  16.  
  17. @Configuration
  18. public class CXFConfig {
  19.  
  20. @Bean
  21. public ServletRegistrationBean dispatcherServlet() {
  22. return new ServletRegistrationBean(new CXFServlet(), "/service/*");
  23. }
  24.  
  25. @Bean(name = Bus.DEFAULT_BUS_ID)
  26. public SpringBus springBus() {
  27. return new SpringBus();
  28. }
  29.  
  30. @Bean
  31. public AExampleDemoWebServiceImpl aExampleDemoWebServiceImpl() {
  32. return new AExampleDemoWebServiceImpl();
  33. }
  34.  
  35. @Bean
  36. public Endpoint endpointWebServiceSampleImpl() {
  37.  
  38. EndpointImpl endpoint = new EndpointImpl(springBus(), aExampleDemoWebServiceImpl());
  39.  
  40. // SOAPHandler 方式
  41. @SuppressWarnings("rawtypes")
  42. List<Handler> handlers = new ArrayList<>();
  43. handlers.add(new JaxServerAuthValidateHeader());
  44. endpoint.setHandlers(handlers);
  45.  
  46. endpoint.publish("/Sample");
  47.  
  48. return endpoint;
  49.  
  50. }
  51.  
  52. }

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

JAX-WS使用Handler实现简单的WebService权限验证的更多相关文章

  1. 一个简单的webservice的demo(下)winform异步调用webservice

    绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...

  2. 一个简单的Webservice的demo,简单模拟服务

    前段时间一直在学习WCF,匆匆忙忙的把<WCF全面解析>和<WCF服务编程>看了一遍,好多东西都不是很懂,又听了一下WCF分布式开发的网络教程,算是马马虎虎的明白点了.回顾了一 ...

  3. 一个简单的webservice调用

    我们先创建一个简单空web应用程序 然后添加新建项目 //我们创建一个peson对象,产生数据标识返回 using System; using System.Collections.Generic; ...

  4. 利用Java编写简单的WebService实例

    使用Axis编写WebService比較简单,就我的理解,WebService的实现代码和编写Java代码事实上没有什么差别,主要是将哪些Java类公布为WebService. 以下是一个从编写測试样 ...

  5. 利用Java编写简单的WebService实例-转载

    使用Axis编写WebService比较简单,就我的理解,WebService的实现代码和编写Java代码其实没有什么区别,主要是将哪些Java类发布为WebService.下面是一个从编写测试例子到 ...

  6. 一个简单的Webservice的demo(中)_前端页面调用

    首先新建项目,这里有两种调用方式,为了能方便理解,新建页面WebserviceTest如下图: 先引用写好的服务,这里用上次写好的服务.见上次写的一个简单的Webservice的demo,简单模拟服务 ...

  7. 一个简单的WebService实例

    WebService在.NET平台下的作用是在不同应用程序间共享数据与数据交换. 要达到这样的目标,Web services要使用两种技术: XML(标准通用标记语言下的一个子集):XML是在web上 ...

  8. (转)Web Service入门简介(一个简单的WebService示例)

    Web Service入门简介 一.Web Service简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从I ...

  9. 利用VS2008发布一个简单的webservice

    一个开发好的webservice,怎样发布出去,供其他电脑访问呢? 本文将介绍如何发布一个简单的webservice,其中的内容都是在网上查看别人文章,自己仿照着做了一遍,因此,难免会发生错误,如果发 ...

随机推荐

  1. Python验证码识别处理实例

    一.准备工作与代码实例 1.PIL.pytesser.tesseract (1)安装PIL:下载地址:http://www.pythonware.com/products/pil/(CSDN下载) 下 ...

  2. LaTeX排版设置图表的位置 Positioning images and tables

    Positioning images and tables LATEX is an editing tool that takes care of the format so you only hav ...

  3. Dede(织梦) CMS SQL Injection Vulnerability

    测试方法: @Sebug.net   dis本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负! # Dede Cms All Versions Sql Vulnerability ...

  4. qt study 泛型和容器

    所谓泛型(generic) 能够像操作基本类型一样轻松操作对象的类和函数. qt容器类就是泛型类,基于模板的泛型类. 重载运算符overloaed operator, 托管容器 managed con ...

  5. Node Server零基础——开发环境文件自动重载

    收录待用,修改转载已取得腾讯云授权 前言 在 web 前端开发中,我们会借助 Grunt.Gulp 和 Webpack 等工具的 Watch 模块去监听文件变化,那服务端应该怎么做?其实文件变化的监听 ...

  6. Hibernate之一对一关联映射

    Hibernate中一对一关联映射共分为两种,一种是一对一主键关联映射,另一种是一对一唯一外键关联映射.下面简单介绍一下这两种关联映射. 一对一主键关联映射 一对一主键关联映射的两个实体有相同的ID. ...

  7. 引导工具GRUB详解

    导读 引导程序是驻留在硬盘第一个扇区(MPR.主引导记录)的程序.GRUB是一个功能强大的多系统引导程序,专门处理Linux与其它操作系统共存的问题.下面就由我介绍一下grub.conf文件里的具体内 ...

  8. html5-video视频播放

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  9. java中 this和super的差别

    this表示当前调用方法的对象的引用: (谁调用这种方法,谁就是这个对象,这个this就是它的引用) 比方: <pre name="code" class="jav ...

  10. Python 3 解析 html

    资料:https://docs.python.org/3/library/html.parser.html python 自带了一个类,叫 HTMLParser. 我们用的时候需要自己定义一个类,继承 ...