设备自动发现开发经验总结
1 整体框架
监控管理 |
过程管理 |
|
ACTION |
Service |
缓冲区 |
Proxy |
WEB SERVICE |
O/X Mapping |
ThreadPool |
2 Web service 开发
2.1 基础扫盲
Web service是一个软件系统,为了支持跨网络的机器之间相互操作交互而设计。它有一个机器可识别的描述格式(特别是WSDL)。不同的系统之间可以通过SOAP消息在规定的方式下相互调用。
简单的说,WebService是一种独立于特定语言、特定平台,基于网络的、分布式的模块化组件。是一个能够使用xml消息通过网络来访问的Interface,这个Interface描述了一组可访问的操作。
WebService一般分为两种:
REST式WebService,基于HTTP协议;
RPC式WebService,基于SOAP协议,不过SOAP也是基于HTTP传输的。
狭义上的WebService是指第二种RPC式的WebService,也就是我们常说的那种。
JAVA中有三种WebService规范,分别是JAX-WS(JAX-RPC)、JAX-RS、JAXM&SAAJ。
这里先说JAX-WS(Java API For XML-WebService),JDK1.6 自带的版本为JAX-WS2.1,其底层支持为JAXB。早期的JAVA Web服务规范JAX-RPC(Java API ForXML-Remote Procedure Call)目前已经被JAX-WS 规范取代,JAX-WS 是JAX-RPC 的演进版本,但JAX-WS 并不完全向后兼容JAX-RPC。
JAX-RS是JAVA EE6 引入的一个新技术。 JAX-RS即Java API for RESTful Web Services,是一个Java 编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建Web服务。JAX-RS使用了Java SE5引入的Java标注来简化Web服务的客户端和服务端的开发和部署。
JAX-RS提供了一些标注将一个资源类,一个POJPJava类,封装为Web资源。标注包括:
@Path,标注资源类或者方法的相对路径
@GET,@PUT,@POST,@DELETE,标注方法是HTTP请求的类型。
@Produces,标注返回的MIME媒体类型
@Consumes,标注可接受请求的MIME媒体类型
@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参数来自于HTTP请求的不同位置,例如@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数,@HeaderParam来自于HTTP请求的头信息,@CookieParam来自于HTTP请求的Cookie。
基于JAX-RS实现的框架有Jersey,RESTEasy等。这两个框架创建的应用可以很方便地部署到Servlet 容器中,比如Tomcat,JBoss等。值得一提的是RESTEasy是由JBoss公司开发的,所以将用RESTEasy框架实现的应用部署到JBoss服务器上,可以实现很多额外的功能。
从本质上来讲 Web 服务就是对外暴露的并能够通过 Web 进行调用的一组 API,它并不要求服务提供方及调用方的技术实现、编程语言、运行平台甚至操作系统等。也正因为这个特点 Web 服务能在企业应用集成领域迅速占领一席之地,并成为实施应用程序集成的首选手段之一,同时 Web 服务也是面向服务架构的重要实现手段。
深入剖析 Web 服务我们不难发现在这个简单定义的背后有若干问题需要解决:Web 服务提供程序如何描述自己才能为调用程序所理解;调用程序如何发现可用的 Web 服务;调用程序在找到需要的 Web 服务后应该如何调用特定的接口。目前业界已经有多个标准以及协议来解决上述问题并支撑 Web 服务的使用,其中最重要的非 WSDL、SOAP、UDDI 莫属。本文以 Java Web 服务为例介绍如何定制行为。
Web 服务基本构件:
WSDL、SOAP 和 UDDI 是 Web 服务中最基础也是最重要的组成部分,这三个协议定义了 Web 服务的描述,发现以及访问。
WSDL(Web Service Description Language):Web 服务描述语言。每个 Web 服务都会有一个相应的 WSDL 文档来进行描述。WSDL 文档首先对接口和访问时的请求 / 响应消息进行抽象描述,然后将其绑定到具体的传输协议和消息格式上以最终定义具体部署的服务访问点。WSDL 文档本质上是一个 XML 格式的文档,其中详细定义了 Web 服务所暴露的接口集合,接口原型,接口参数、返回类型的数据结构,接口调用消息格式,承载协议等。
SOAP(Simple Object Access Protocol):简单对象访问协议。SOAP 协议本质上就是 XML 和 HTTP 协议的组合体,它定义了一个 XML 格式的 Web 服务访问消息封装格式并通过 HTTP 协议进行消息承载,当然 SOAP 消息也可以通过 HTTPS 或者 SMTP 等协议来承载。
- SOAP 指简易对象访问协议
- SOAP 是一种通信协议
- SOAP 用于应用程序之间的通信
- SOAP 是一种用于发送消息的格式
- SOAP 被设计用来通过因特网进行通信
- SOAP 独立于平台
- SOAP 独立于语言
- SOAP 基于 XML
- SOAP 很简单并可扩展
- SOAP 允许您绕过防火墙
SOAP 将被作为 W3C 标准来发展
具体可参考:http://www.w3school.com.cn/soap/index.asp
UDDI(Universal Description, Discovery and Integration):统一描述、发现和集成协议。它是为解决 Web 服务的发布和发现问题而制订的技术标准,包含一组基于 Web 的、分布式的 Web 服务信息注册中心的实现标准,以及一组使企业能将自己提供的 Web 服务注册到该中心的实现标准。
2.2 框架介绍
按照国标草案所相关标准,不仅ITSM 需要通过Web Service 从NMS 的监控管理获取数据,过程管理也需要提供相关接口让监控模块来进行调用。二者之间的操作是相互的。
所以过程管理即我们的ITSM系统也需要向外界提供web service访问接口。
首先介绍下最常用的web service 框架。
2.2.1 Apache CXF
Apache CXF 是一个开源的 Services 框架,吸收了Celtix 和 XFire 两大开源项目的精华,提供了对JAX-WS全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL 优先(WSDL First)来轻松地实现 Web Services 的发布和使用。Apache CXF已经是一个正式的Apache顶级项目。
CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTful HTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS 或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。
CXF 包含了大量的功能特性,但是主要集中在以下几个方面:
支持 Web Services 标准:CXF 支持多种 Web Services 标准,包含 SOAP、Basic Profile、WS-Addressing、WS-Policy、WS-ReliableMessaging 和WS-Security。
灵活部署:JBoss、WebSphere Application Server 和 WebLogic Application Server,以及 Jetty 和 Tomcat;独立的 Java 客户端/服务器。
支持多种编程语言:提供跨平台访问。支持 json 以及提供REST服务支持
Java to WSDL;WSDL to Java;XSD to WSDL;WSDL to XML;WSDL to SOAP;WSDL to Service
2.2.2 Java6 Web Service
从JavaSE6.0开始,Java引入了对Web Service的原生支持。我们只需要简单的使用Java的Annotation标签即可将标准的Java方法发布成Web Service。大大减少了项目安装部署的代价,因为选择开源的框架依赖大量第三方包,程序的尺寸倍增。.
2.2.3 Apache Axis2
Apache Axis2是Axis的后续版本,是新一代的SOAP引擎。他有如下特点:
1)采用名为 AXIOM(AXIs Object Model)的新核心 XML 处理模型,利用新的XML解析器提供的灵活性按需构造对象模型。
2)支持不同的消息交换模式。目前Axis2支持三种模式:In-Only、Robust-In和In-Out。In-Only消息交换模式只有SOAP请求,而不需要应答;Robust-In消息交换模式发送SOAP请求,只有在出错的情况下才返回应答;In-Out消息交换模式总是存在SOAP请求和应答。
3)提供阻塞和非阻塞客户端 API。
4)支持内置的 Web服务寻址 (WS-Addressing) 。
5)灵活的数据绑定,可以选择直接使用 AXIOM,使用与原来的 Axis 相似的简单数据绑定方法,或使用 XMLBeans、JiBX 或 JAXB 2.0 等专用数据绑定框架。
6)新的部署模型,支持热部署。
7)支持HTTP,SMTP,JMS,TCP传输协议。
8)支持REST (Representational State Transfer)。
Axis2与CXF的对比
1. Apache CXF 是根据Spring哲学来进行编写的,CXF是无缝集成spring,可以只要配置bean就行了,而Axis2对于spring的集成有几种选择,反而容易混淆,要复杂一些(比如要配置services),不如CXF简单。
2. Axis2实现了模块化,对于各种WS-*的应用可选择,而CXF都包含在一起。
3. Axis2支持更广泛的数据并对,如XMLBeans,JiBX,JaxMe和JaxBRI和它自定义的数据绑定ADB。注意JaxME和JaxBRI都还是试验性的。CXF只支持JAXB和Aegis。
4. Axis2支持JAX-RPC,不完全支持JAX-WS,可以与一些老版本兼容,而CXF是基于JAX-WS。
5. Axis2还支持C/C++的版本
2.2.4 框架比较
如果你需要多语言的支持,你应该选择AXIS2。但是Axis2支持JAX-RPC,不完全支持JAX-WS,与一些老版本不兼容,Axis2的部署吓死人,太多东西而实际上很多用不到。而CXF是基于JAX-WS。
如果你需要把你的实现侧重JAVA并希望和Spring的无缝集成,CXF就是更好的选择,特别是把你的Web Service嵌入其他的程序中。
如果你只是需要在java6环境下开发,大大减少了项目安装部署的代价,因为选择开源的框架依赖大量第三方包,程序的尺寸倍增。
基于与现有系统特别是Spring的集成便利性以及考虑到不同厂商和生产环境中JAVA版本的不同,经过讨论,我们采用CXF作为我们的Web Service框架。
2.3 入门实例
本文对比和总结了各种web service开发技术,决定选取cxf 作为ITSM提供接口的web service 框架,并与ITSM中的spring进行整合。
2.3.1 服务器端相关开发
备注:以下内容均基于真实开发环境,在eclipse3.5和SSH(Struts2+hibernat3+spring2.5)中测试通过。 |
1、 CXF官方网址:http://cxf.apache.org/
2、 Jar包下载地址:http://www.apache.org/dyn/closer.cgi?path=/cxf/2.3.3/apache-cxf-2.3.3.zip
将下来的jar包解压后,目录大概就这样
其中:
Bin:目录提供的是常用的dos控制台命令工具
docs :帮助文档
lib:jar包、依赖库
lib-samples:也是jar包,有jetty、httpclients、junit等jar包
modules:打包好的WebService模块
samples:示例demo
3、 需要的jar包如下,在开发之前,需要将如下包导入到项目中
4、 首先在web.xml中添加如下配置:
<!--Apache cxf 配置文件--> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet>
<servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> |
5、 编写web service 服务器端的接口与实现
@WebService publicinterface AutoDiscAndSyncManager {
/** * description : 获取配置项ID列表方法 * @param ciType:配置项类型 * @return 监控对象ID集合 */ public String[] getMoIds(String ciType);
/** * description :模拟监控模块应该提供的接口获取指定监控对象的属性列表方法 * * @param moId * : 监控对象ID * @return */ public String getMoAttributeNames(@WebParam(name = "moId") String moId);
/** * description:获取指定监控对象的特定属性的值方法 * * @param moId * @param attributeName * @return */ public String getMoAttributeValue( @WebParam(name = "moId") String moId, @WebParam(name = "attributeName") String attributeName);
}
|
具体的接口实现这里就不描述了。
6、 接口发布。cxf既可以通过 JaxWsServerFactoryBean来发布接口,也可以通过与Spring 无缝集成的方式来发布。这里仅提供配置文件的方式。
编写服务器端配置文件,这里spring的Bean 进行绑定 。
在/src目录中,新建一个applicationContext-client-server.xml文件(名称可自己任意命名),文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="autoDiscAndSyncManagerImpl" address="/autoDiscAndSyncManagerImpl" implementor="com.dhcc.itsm.cmdb.service.impl.AutoDiscAndSyncManagerImpl" /> </beans> |
注意上面的红色加粗部分,这个很重要的哦!
7、 启动tomcat服务器后,在浏览器中打开如下路径:
http://localhost:8080/项目名称/services/autoDiscAndSyncManagerImpl?wsdl
XML Source Code <?xml version="1.0" ?><wsdl:definitions name="AutoDiscAndSyncManagerImplService" targetNamespace="http://impl.service.cmdb.itsm.dhcc.com/" xmlns:ns1="http://service.cmdb.itsm.dhcc.com/" xmlns:ns2="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://impl.service.cmdb.itsm.dhcc.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:import location="http://localhost:8080/fvsd/services/autoDiscAndSyncManagerImpl?wsdl=AutoDiscAndSyncManager.wsdl" namespace="http://service.cmdb.itsm.dhcc.com/"> </wsdl:import> <wsdl:binding name="AutoDiscAndSyncManagerImplServiceSoapBinding" type="ns1:AutoDiscAndSyncManager"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"></soap:binding> <wsdl:operation name="getMoIds"> <soap:operation soapAction="" style="document"></soap:operation> <wsdl:input name="getMoIds"> <soap:body use="literal"></soap:body> </wsdl:input> <wsdl:output name="getMoIdsResponse"> <soap:body use="literal"></soap:body> </wsdl:output> </wsdl:operation> <wsdl:operation name="getMoAttributeValue"> <soap:operation soapAction="" style="document"></soap:operation> <wsdl:input name="getMoAttributeValue"> <soap:body use="literal"></soap:body> </wsdl:input> <wsdl:output name="getMoAttributeValueResponse"> <soap:body use="literal"></soap:body> </wsdl:output> </wsdl:operation> <wsdl:operation name="getMoAttributeNames"> <soap:operation soapAction="" style="document"></soap:operation> <wsdl:input name="getMoAttributeNames"> <soap:body use="literal"></soap:body> </wsdl:input> <wsdl:output name="getMoAttributeNamesResponse"> <soap:body use="literal"></soap:body> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="AutoDiscAndSyncManagerImplService"> <wsdl:port binding="tns:AutoDiscAndSyncManagerImplServiceSoapBinding" name="AutoDiscAndSyncManagerImplPort"> <soap:address location="http://localhost:8080/fvsd/services/autoDiscAndSyncManagerImpl"></soap:address> </wsdl:port> </wsdl:service> </wsdl:definitions>
|
如果你能看到以上wsdl的xml文件的内容,就说明你成功了。
备注:1、这里的项目名称就是自己的项目的命名。2、autoDiscAndSyncManagerImpl是服务器端配置文件<jaxws:endpoint>指定的addresss的值。 |
2.3.2 客户端相关开发
这里的客户端相关开发主要是针对JAVA 语言。
客户端方面主要有三种方式:
Ø 通过JaxWsProxyFactoryBean 的方式进行调用。
Ø 通过Spring Bean配置文件的方式进行调用。
Ø 通过JaxWsDynamicClientFactory类。只要指定服务器端wsdl文件的位置,然后指定要调用的方法和方法的参数即可
其中1、2种方法必须依赖于服务器端提供的接口(简单点,就是服务器端必须把相关接口抽取出来打成jar 包提供给客户端);第三种方式则不依赖于客户端
下面分别给予介绍。
1、 通过JaxWsProxyFactoryBean 的方式进行调用
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(AutoDiscAndSyncManager.class); factory.setAddress ("http://localhost:8080/fvsd/services/autoDiscAndSyncManagerImpl"); AutoDiscAndSyncManager manager = (AutoDiscAndSyncManager) factory.create(); System.out.println(manager.getAttributeKeyValueByIp("", "")); |
2、 通过Spring Bean配置文件的方式进行调用。
下面我们将Client端也通过Spring配置完成整合。首先增加applicationContext-client.xml配置文件,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<!-- Import apache CXF bean definition --> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <jaxws:client id="autoDiscAndSyncManager" serviceClass="com.dhcc.itsm.cmdb.service.AutoDiscAndSyncManager" address="http://localhost:8080/fvsd/services/autoDiscAndSyncManagerImpl"> </jaxws:client> </beans> |
3、 通过JaxWsDynamicClientFactory类
JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance(); Client client = clientFactory.createClient( "http://localhost:8080/fvsd/services/autoDiscAndSyncManagerImpl?wsdl" ); Object[] result = client.invoke("getMoAttributeKeyValue","adfc"); System.out.println(result[0]); |
2.4 数据绑定
Apache CXF有多种数据绑定方式,如:Aegis 、Databinding、JAXB、MTOM Attachments 。 其中JAXB(JavaTM Architecture for XML Binding)是其默认的数据绑定方式。JAXB是一套自动映射XML和Java实例的开发接口和工具。
2.4.1 Web 服务中的数据绑定
通俗来讲,XML 形式数据和应用程序业务数据结构的转换过程就称为数据绑定。XML 以其特有的平台独立性可以很好的用来描述 Web 服务,但是 Web 服务的核心仍在于应用程序业务逻辑处理,在业务逻辑处理中需要的业务数据结构而非这些 XMl 格式的数据,因此就需要数据绑定来完成从 XML 格式数据到应用程序业务数据结构的转换。从上节我们不难看出 Web 服务在通信过程中均以 XML 形式进行表示的,而在 Java Web 服务的提供端和调用端又是以 Java 对象形式存在,因此就必然需要一个 XML 和 Java 之间的一个双向转换过程,这个转换过程就是 XML 和 Java 的数据绑定。目前业界有很多数据绑定实现,比如 adb、xmlbeans、jibx、jaxme、jaxb 等,可以根据项目实际情况进行选择,像 Axis2 里就是用了自己的 adb 绑定框架,而 JAX-RPC 类型 Web 服务就有自己的绑定机制。下图直观地反映了 Java Web 服务调用过程中的数据绑定。
2.4.2 JAXB 框架概述
JAXB(Java Architecture for XML Binding)是由 J2EE 体系中标准的 XML schema 和 Java 数据绑定框架,开发者可以使用 JAXB 方便地在 Java 应用程序中进行 XML 数据和 Java 对象的转换。JAXB 提供了将 XML 文档解析为 Java 内容树的方法,以及将 Java 内容树重新写回 XML 文档的方法。同时 JAXB 还提供了基于 XML schema 生成 Java 类以及从 Java 类生成 XML schema 的支持。JAXB 框架分为以下三个组成部分:
schema 编译器:schema 编译器以 XML schema 为输入生成和 schema 相对应的 Java 类集,生成的 Java 类中会根据 schema 的结构自动包含了相应的 JAXB 注解。比方说 schema 里的一个元素映射的 Java 类会自动用 @XmlType 注解加以标注,一个元素的属性所映射的 Java 字段会自动用 @XmlElement 注解加以标注;
schema 生成器:schema 生成器以包含 JAXB 注解的 Java 类集为输入生成相应的 XML schema。比方说一个包含 @XmlType 注解的 Java 类在生成的 schema 中会被映射为一个元素;
JAXB 运行环境:JAXB 运行时环境提供了两个基本的操作用于 XML 文档的访问,操作以及验证等等:marshal、unmarshal,这两个操作也是 XML 和 Java 绑定的基础。Marshal 是指将一个内存对象以 XML 文档形式进行编组处理的过程,unmarshal 则是一个相反的过程,将一个 XML 文档解析为内存对象的过程。
2.4.3 JAXB 的基础 -XML schema
XML schema 是 XML 文档的格式定义,是 DTD 的替代产品用于约束 XML 文档内容及结构,比如它定义了 XML 文档可以出现的元素,元素出现的顺序,元素具有的属性等。XML schema 本身就是一个 XML 文档,因此天然具有了 XML 的可扩展性。同时 XML schema 对 XML 数据类型提供了更为丰富的支持。JAXB 框架的基础就是 XML schema,一个使用 JAXB 的典型场合就是根据业务数据模型需要先写出 XML schema,然后利用 JAXB 框架的绑定编译器直接生成 XML 相应的 Java 类集。
2.4.4 JAXB 与 Web 服务关系
JAX-WS 型 Web 服务将 XML 和 Java 之间的绑定代理给了 JAXB 来完成,也就是说在 Web 服务调用过程中的 XML 数据和 Java 对象间转换都是由 JAXB 框架来完成的。Web 服务中接口引用的参数、返回类型等等数据类型描述都是在关联的 XML schema 中定义的,而 JAXB 框架也正是根据这个 Web 服务关联的 XML schema 来完成于 Java 对象之间的相互映射。
2.4.5 JAXB 框架定制支持
JAXB 规范定义了 XML schema 与 Java 的标准映射关系,比方说 XML 的 xsd:string 数据类型映射为 Java.lang.String,所有 JAXB 规范实现者必须实现规范所定义的标准的 XML schema 与 Java 的映射。在大多数情况下标准映射已经能满足开发者编程需要,但是不排除在一些特殊场合我们需要定制或重载 JAXB 规范定义的标准映射,比方说我们想把 xsd:string 映射到我们自己的一个 Javabean 而非标准映射里的 Java.lang.String 类,或者我们希望对 XML schema 编译器产生的 Java 类集增加 Java doc 支持,甚至定制产生的 Java 类的名字等等,这个时候我们就需要对 JAXB 标准映射进行定制。
JAXB 提供了两种方式支持从 XML schema 到 Java 的绑定定制,定制通常是以定制声明形式完成。
schema 内置注解:开发者可以通过在 XML schema 文档中用注解方式进行定制声明,这种定制方式开发者可以直观的看到定制声明的作用对象,作用域等,通常用于比较简单的绑定定制。schema 内置定制声明通常的语法格式如下:
<xs:annotation> <xs:appinfo> ..... binding declaration ..... </xs:appinfo> </xs:annotation> |
schema 外部绑定定制文件:开发者可以把定制声明编写在一个单独的文件中,然后在编译 schema 时指定这个定制文件,这类定制文件通常以 .xjb 扩展名命名。这种方式便于 schema 定制声明的集中化管理。外部绑定定制文件中的定制声明通常的语法格式如下:
<jxb:bindings> <jxb:bindings> <binding declaration> <jxb:bindings> </jxb:bindings> |
从 Java 到 XML schema 的映射开发者可以通过 JAXB 提供的注解来完成,在编程 Java 类时可以使用 JAXB 丰富的注解轻松地完成绑定定制。
开发者可以在全局、schema、组件等不同层次上进行进行定制声明,相应不同的声明作用域。
2.5 WS-Security
2.5.1 引言
如果所有系统都运行在一个封闭的局域网内,那么可以不考虑网络攻击,拒绝服务,消息篡改,窃取等问题。但通常情况都接入互联网,那么我就得考虑信息安全问题,像前面那样直接将消息明文传输,肯定不行。那么,我们就得给消息加密。CXF可以结合WSS4J来对消息安全进行管理,可以使用令牌,X.509认证对消息头或内容进行加密。
这节可参考官方网站内容:http://cxf.apache.org/docs/ws-security.html。
以下是官方的一个简单介绍:
WS-Security provides means to secure your services above and beyond transport level protocols such as HTTPS. Through a number of standards such as XML-Encryption, and headers defined in the WS-Security standard, it allows you to:
- Pass authentication tokens between services
- Encrypt messages or parts of messages
- Sign messages
- Timestamp messages
Currently, CXF implements WS-Security by integrating WSS4J. To use the integration, you'll need to configure these interceptors and add them to your service and/or client.
2.5.2 WSS4J
由上文我们提到了WSS4J。要了解CXF的安全模块,必须先了解下WSS4J.
WSS4J和CXF 一样,也是Apache 的一个开源项目。他提供了目前主流的web服务安全标准的java 实现。简称:ws-security。它主要实现了以下几个安全标准:
- SOAP Message Security 1.1
- Username Token Profile 1.1
- X.509 Certificate Token Profile 1.1
- SAML Token Profile 1.1
- Kerberos Token Profile 1.1
- Basic Security Profile 1.1
WSS4J在Web Services框架中以handler方式工作,在发送SOAP消息前进行签名、加入认证凭据和加密,在收到SOAP消息后进行解密、认证和验证签名等安全工作。使用者可以自己编写handler处理SOAP消息以保证安全。
Apache CXF 的 WS-Security 实现基于开放源码的 WSS4J 库。
下图是WSS4J的工作流程图。
更多信息可以去apache wss4j 官方网站上进行了解:http://ws.apache.org/wss4j/
2.5.3 基于UsernameToken的安全验证
正如上面介绍的,ws-security提供了用户名令牌(UsernameToken)、消息加密(Encrypt messages)、消息签名(Sign messages)、时间戳(Timestamp messages)等方式。CXF通过WSS4J来实现了web服务安全的标准。根据业务需要,可以选择不同的实现。这里只实现基于UsernameToken 的安全验证。
UsernameToken 是向 WS-Security 提供用户名和密码对的标准方法。可以以明文形式发送密码信息(通常只在与 Transport Layer Security [TLS] 或 WS-Security 加密结合使用时用于生产环境,但是便于测试),也可以以散列值形式发送。它对于需要直接身份验证的许多应用程序很方便。
UsernameToken 身份验证与HTTP身份验证很相似,此时用户保密信息在消息的头部被传送。UsernameToken被添加到SOAP的头部,可能还会夹杂着一个散列的口令。这是一种加密的简单形式,可以避免无限制地传递口令。应该使用传输级别或者消息级别的加密来保证用户口令的保密性。
2.5.4 实现例子
例子是基于服务器端采用spring 配置文件,客户端采用程序来进行实现。也可以通过服务器端和客户端都通过Spring的配置文件来进行实现。
Ø 服务器端方面
u 拦截器配置
<bean id="serverPasswordCallback" class="com.dhcc.itsm.webservice.server.security.ServerSecurityHandler"> … …
<jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/> <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" /> <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> <constructor-arg> <map> <entry key="action" value="UsernameToken" /> <entry key="passwordType" value="PasswordDigest" />
<entry key="passwordCallbackRef"> <ref bean="serverPasswordCallback" /> </entry> </map> </constructor-arg> </bean> </jaxws:inInterceptors> |
解释下:
1、 Action:UsernameToken指使用用户令牌
2、 passwordType:PasswordText指密码加密策略,这里直接明文,其他选项还有:PasswordDigest代表通过MD5进行加密。
3、 User:cxfServer指别名 。
4、 passwordCallBackRef:serverPasswordCallback:验证密码的回调类,这个类必须实现CallbackHandler接口。
5、 org.apache.cxf.binding.soap.saaj.SAAJInInterceptor :此拦截器在cxf2.1之后不需要再配置。
u 密码验证回调类
publicclass ServerSecurityHandler implements CallbackHandler { publicvoid handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; String id = pc.getIdentifier(); if (id.equals("admin")) { //千万不要忘了这句,否则会导致非空指针的错误 pc.setPassword("admin"); } else { thrownew SecurityException(" auth failed"); } } } |
Ø 客户端方面
u 拦截器配置
WSS4JOutInterceptor拦截器,表示发出请求的时候将以提供的用户名和密码信息提交到服务器端认证 Map<String, Object> outPropsMap=new HashMap<String, Object>(); //表示验证机制是用户姓名令牌,也就是使用传统的用户名和密码机制 outPropsMap.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); //用于初始化用户名,这是一个必选项 outPropsMap.put(WSHandlerConstants.USER, "admin"); //明文验证 outPropsMap.put(WSHandlerConstants.PASSWORD_TYPE,WSConstants.PW_DIGEST); //表示客户端验证密码的回调类,这个类必须实现CallbackHandler接口 outPropsMap.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientSecurityHandler.class.getName()); JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.getOutInterceptors().add(new LoggingOutInterceptor()); //cxf2.1以上不再需要SAAJOutInterceptor factory.getOutInterceptors().add(new SAAJOutInterceptor()); //WSS4JOutInterceptor拦截器 factory.getOutInterceptors().add(new WSS4JOutInterceptor(outPropsMap)); factory.getServiceFactory().setDataBinding(new JAXBDataBinding()); factory.setServiceClass(AutoDiscAndSyncManager.class); factory.setAddress("http://localhost:8080/fvsd/services/AutoDiscAndSyncManager"); AutoDiscAndSyncManager manager = (AutoDiscAndSyncManager)factory.create(); List<CiPosition> pList=manager.getAllPositions(); JAXBContext context = JAXBContext.newInstance(CiPosition.class); Marshaller marshaller = context.createMarshaller(); marshaller.marshal(pList.get(0), System.out); } |
解释:
红色加粗部分就是客户端相关配置,配置当然也可以通过spring 配置文件的方式来实现。具体可以参考服务器端相关的配置。
u 密码验证回调类
publicclass ClientSecurityHandler implements CallbackHandler {
publicvoid handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pc = (WSPasswordCallback) callbacks[i]; int usage = pc.getUsage(); if (usage == WSPasswordCallback.USERNAME_TOKEN) { pc.setIdentifier("admin"); pc.setPassword("admin"); } } } } |
2.6 其他
1、主要针对java 系统,对于非java 系统的解决方案?
2、数据传输是用xml 还是直接对象呢?对象对与Date类型,HashMap等
3、数据绑定到时是在服务器处理还是客户端进行处理呢?
4、JMS
5、密码