cxf添加拦截器应用

项目中有时候也会做一些类似于权限验证的东西,拦截器也是一种实现方式。拦截器主要作用是做一些权限过滤,编码处理等。

webService接口也可以上拦截器,我们也可以给webservice请求加权限判断功能;

webservice分服务端和客户端,服务端和客户端都是可以加拦截器的,无论是服务端还是客户端,都分进,出(In,Out)拦截器;

可以使用cxf内置拦截器,也可以自定义拦截器,无论是自定义的拦截器,还是CXF自带的拦截器,都必须实现Interceptor接口。

下面分别从这两个方面来讲解:

一、cxf内置拦截器

这里以日志拦截器为例:

服务端的Server类:

 1 /**
 2  *
 3  */
 4 package com.hik.webservice;
 5
 6 import javax.xml.ws.Endpoint;
 7
 8 import org.apache.cxf.interceptor.LoggingInInterceptor;
 9 import org.apache.cxf.interceptor.LoggingOutInterceptor;
10 import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
11
12 import com.hik.webservice.impl.HelloWorldImpl;
13
14 /**
15  * @ClassName: Server
16  * @Description: TODO
17  * @author jed
18  * @date 2017年7月30日上午10:26:16
19  *
20  */
21 public class Server {
22
23     public static void main(String[] args) {
24         System.out.println("web Service start");
25         HelloWorldImpl implementor = new HelloWorldImpl();
26         String address="http://192.168.0.102/helloWorld";
27         //Endpoint.publish(address, implementor);//JDK实现
28         JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
29         factoryBean.setAddress(address); //设置暴露地址
30         factoryBean.setServiceClass(HelloWorld.class); //接口类
31         factoryBean.setServiceBean(implementor); //设置实现类
32         factoryBean.getInInterceptors().add(new LoggingInInterceptor()); //添加in拦截器  日志拦截器
33         factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); // 添加out拦截器
34         factoryBean.create();
35         System.out.println("web Service started");
36
37     }
38 }

通过factoryBean对象可以获取拦截器组,添加进或者出拦截器。日志拦截器是经典的拦截器,开发经常用到。

我们可以把客户端的请求,以及服务端返回的信息打印出来,可以打印控制台,也可以打印到执行文件;这里为了演示方便,直接搞无参的拦截器,

打印到控制台;

执行下Server类:

再来执行下客户端的Client类,结果:

我们可以看到服务端server控制台有日志输出,仔细观察Server端的控制台:

 1 八月 05, 2017 9:21:35 上午 org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld
 2 信息: Inbound Message
 3 ----------------------------
 4 ID: 1
 5 Address: http://192.168.0.102/helloWorld?wsdl
 6 Http-Method: GET
 7 Content-Type:
 8 Headers: {Accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive], Content-Type=[null], Host=[192.168.0.102], User-Agent=[Java/1.7.0_79]}
 9 --------------------------------------
10 八月 05, 2017 9:21:36 上午 org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld
11 信息: Inbound Message
12 ----------------------------
13 ID: 2
14 Address: http://192.168.0.102/helloWorld
15 Encoding: UTF-8
16 Http-Method: POST
17 Content-Type: text/xml; charset=UTF-8
18 Headers: {Accept=[text/xml, multipart/related], connection=[keep-alive], Content-Length=[170], content-type=[text/xml; charset=UTF-8], Host=[192.168.0.102], SOAPAction=[""], User-Agent=[JAX-WS RI 2.2.4-b01]}
19 Payload: <?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:getRoles xmlns:ns2="http://webservice.hik.com/"/></S:Body></S:Envelope>
20 --------------------------------------
21 八月 05, 2017 9:21:37 上午 org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld
22 信息: Outbound Message
23 ---------------------------
24 ID: 2
25 Response-Code: 200
26 Encoding: UTF-8
27 Content-Type: text/xml
28 Headers: {}
29 Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getRolesResponse xmlns:ns2="http://webservice.hik.com/"><return><item><key>jack</key><value><id>3</id><roleName>程序员</roleName></value></item><item><key>admin</key><value><id>1</id><roleName>技术总监</roleName></value><value><id>2</id><roleName>产品经理</roleName></value></item></return></ns2:getRolesResponse></soap:Body></soap:Envelope>
30 --------------------------------------

这里的打印出来的就是日志信息:Inbound 进信息  Outbound 是出信息,进的时候,大家会看到有个Headers SOAP消息。后面我们可以在里面加我们的数据;

在Outbound Message里,Payload消息里我们可以找到webservice返回的数据 SOAP消息;

客户端也可以加进出拦截器,修改Client代码:

我们用到了ClientProxy,客户端代理

请求的时候,可以看到控制台的日志信息:(日志和服务端一样)

 1 八月 05, 2017 10:05:22 上午 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
 2 信息: Creating Service {http://webservice.hik.com/}HelloWorldService from WSDL: http://192.168.0.102/helloWorld?wsdl
 3 八月 05, 2017 10:05:22 上午 org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld
 4 信息: Outbound Message
 5 ---------------------------
 6 ID: 1
 7 Address: http://192.168.0.102/helloWorld
 8 Encoding: UTF-8
 9 Http-Method: POST
10 Content-Type: text/xml
11 Headers: {Accept=[*/*], SOAPAction=[""]}
12 Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getRoles xmlns:ns2="http://webservice.hik.com/"/></soap:Body></soap:Envelope>
13 --------------------------------------
14 八月 05, 2017 10:05:23 上午 org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld
15 信息: Inbound Message
16 ----------------------------
17 ID: 1
18 Response-Code: 200
19 Encoding: UTF-8
20 Content-Type: text/xml; charset=UTF-8
21 Headers: {content-type=[text/xml; charset=UTF-8], Date=[Sat, 05 Aug 2017 02:05:22 GMT], Server=[Jetty(9.2.15.v20160210)], transfer-encoding=[chunked]}
22 Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:getRolesResponse xmlns:ns2="http://webservice.hik.com/"><return><item><key>jack</key><value><id>3</id><roleName>程序员</roleName></value></item><item><key>admin</key><value><id>1</id><roleName>技术总监</roleName></value><value><id>2</id><roleName>产品经理</roleName></value></item></return></ns2:getRolesResponse></soap:Body></soap:Envelope>
23 --------------------------------------
24 jack:
25 3,程序员
26
27 admin:
28 1,技术总监
29 2,产品经理 

二、自定义拦截器

根据特殊需求,可能需自定义拦截器。如:客户端访问服务端webservice接口要加权限认证。

实现思路:

我们可以通过在SOAP消息的Header头信息中添加自定义信息,然后发送到服务端端,服务器端通过获取

Header头消息,然后进行认证;这里的添加消息,和获取消息认证,我们都是通过自定义拦截器来实现;

首先是服务器端:

我们自定义拦截器:MyInterceptor  继承AbstractPhaseInterceptor (最终也是实现Interceptor接口)即可。实现handleMessage方法即可。

自定义实现的拦截器:我们主要是获取Header头消息,然后获取userName和password节点,然后获取值,进行权限判断,假如认证不通过,我们抛出异常;

 1 /**
 2  *
 3  */
 4 package com.hik.interceptor;
 5
 6
 7 import java.util.List;
 8
 9 import org.apache.cxf.binding.soap.SoapMessage;
10 import org.apache.cxf.headers.Header;
11 import org.apache.cxf.interceptor.Fault;
12 import org.apache.cxf.phase.AbstractPhaseInterceptor;
13 import org.apache.cxf.phase.Phase;
14 import org.w3c.dom.Element;
15 import org.w3c.dom.NodeList;
16
17 /**
18  * @ClassName: MyInterceptor
19  * @Description: 自定义拦截器
20  * @author jed
21  * @date 2017年8月5日上午10:20:09
22  *
23  */
24 public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
25     /**
26      *
27      */
28     public MyInterceptor() {
29         // 在调用方法之前调用拦截器
30         super(Phase.PRE_INVOKE);
31     }
32
33     public void handleMessage(SoapMessage message) throws Fault {
34         List<Header> heads = message.getHeaders();
35         if(heads==null|| heads.size()==0){
36             throw new Fault(new IllegalArgumentException("没有Header,拦截器实施拦截"));
37         }
38         Header firstHeader = heads.get(0);
39         Element element = (Element) firstHeader.getObject();
40         NodeList userIds = element.getElementsByTagName("userName");
41         NodeList userPasses = element.getElementsByTagName("password");
42         if(userIds.getLength()!=1){
43             throw new Fault(new IllegalArgumentException("用户名格式不对"));
44         }
45         if(userPasses.getLength()!=1){
46             throw new Fault(new IllegalArgumentException("密码格式不对"));
47         }
48
49         String userId = userIds.item(0).getTextContent();
50         String userPass = userPasses.item(0).getTextContent();
51         if(!userId.equals("admin")|| !userPass.equals("12345")){
52             throw new Fault(new IllegalArgumentException("用户名或者密码不正确"));
53         }
54     }
55
56 }

在Server类里,我们要添加一个in 拦截器,在进入的时候,我们要进行验证;

 1 /**
 2  *
 3  */
 4 package com.hik.webservice;
 5
 6 import javax.xml.ws.Endpoint;
 7
 8 import org.apache.cxf.interceptor.LoggingInInterceptor;
 9 import org.apache.cxf.interceptor.LoggingOutInterceptor;
10 import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
11
12 import com.hik.interceptor.MyInterceptor;
13 import com.hik.webservice.impl.HelloWorldImpl;
14
15 /**
16  * @ClassName: Server
17  * @Description: TODO
18  * @author jed
19  * @date 2017年7月30日上午10:26:16
20  *
21  */
22 public class Server {
23
24     public static void main(String[] args) {
25         System.out.println("web Service start");
26         HelloWorldImpl implementor = new HelloWorldImpl();
27         String address="http://192.168.0.102/helloWorld";
28         //Endpoint.publish(address, implementor);//JDK实现
29         JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();
30         factoryBean.setAddress(address); //设置暴露地址
31         factoryBean.setServiceClass(HelloWorld.class); //接口类
32         factoryBean.setServiceBean(implementor); //设置实现类
33         factoryBean.getInInterceptors().add(new LoggingInInterceptor()); //添加in拦截器  日志拦截器
34         factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); // 添加out拦截器
35
36         factoryBean.getInInterceptors().add(new MyInterceptor());// 添加自定义拦截器
37         factoryBean.create();
38         System.out.println("web Service started");
39
40     }
41 }

客户端代码:

我们同样要添加一个自定义拦截器:AddHeaderInterceptor,主要是在拦截器里创建头消息;请求服务器端传入头信息为服务器接收验证。

 1 /**
 2  *
 3  */
 4 package com.hik.interceptor;
 5
 6 import java.util.List;
 7
 8 import javax.xml.namespace.QName;
 9
10 import org.apache.cxf.binding.soap.SoapMessage;
11 import org.apache.cxf.headers.Header;
12 import org.apache.cxf.helpers.DOMUtils;
13 import org.apache.cxf.interceptor.Fault;
14 import org.apache.cxf.phase.AbstractPhaseInterceptor;
15 import org.apache.cxf.phase.Phase;
16 import org.w3c.dom.Document;
17 import org.w3c.dom.Element;
18
19
20 /**
21  * @ClassName: AddHeaderInterceptor
22  * @Description: TODO
23  * @author jed
24  * @date 2017年8月5日上午10:59:13
25  *
26  */
27 public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
28
29     private String userName;
30     private String password;
31
32     /**
33      * @param userName
34      * @param password
35      */
36     public AddHeaderInterceptor(String userName, String password) {
37         super(Phase.PREPARE_SEND); // 发送SOAP消息之前调用拦截器
38         this.userName = userName;
39         this.password = password;
40     }
41
42     public void handleMessage(SoapMessage message) throws Fault {
43         List<Header> heads = message.getHeaders();
44         Document doc = DOMUtils.createDocument();
45         Element ele = doc.createElement("authHeader");
46         Element idElement = doc.createElement("userName");
47         idElement.setTextContent(userName);
48         Element passElement = doc.createElement("password");
49         passElement.setTextContent(password);
50         ele.appendChild(idElement);
51         ele.appendChild(passElement);
52
53         heads.add(new Header(new QName("admin"), ele));
54     }
55
56
57 }

Client类里我们要修改下,加下Out 拦截器:

 1 /**
 2  *
 3  */
 4 package com.hik.webservice;
 5 import java.util.List;
 6
 7 import org.apache.cxf.frontend.ClientProxy;
 8 import org.apache.cxf.interceptor.LoggingInInterceptor;
 9 import org.apache.cxf.interceptor.LoggingOutInterceptor;
10
11 import com.hik.interceptor.AddHeaderInterceptor;
12 /**
13  * @ClassName: Client
14  * @Description: TODO
15  * @author jed
16  * @date 2017年7月30日下午1:58:36
17  *
18  */
19 public class Client {
20
21     public static void main(String[] args) {
22         HelloWorldService service = new HelloWorldService();
23         HelloWorld helloWorld = service.getHelloWorldPort(); //代理
24         org.apache.cxf.endpoint.Client client =ClientProxy.getClient(helloWorld);
25         //client.getInInterceptors().add(new LoggingInInterceptor()); // 添加in拦截器   日志拦截器
26         client.getOutInterceptors().add(new AddHeaderInterceptor("admin", "12345")); // 添加自定义拦截器
27         client.getOutInterceptors().add(new LoggingOutInterceptor()); // 添加out拦截器
28         //org.apache.cxf.frontend.ClientProxy
29         //System.out.println(helloWorld.say("你好!"));
30         /*User user = new User();
31         user.setUserName("lili");
32         user.setPassword("123456");
33         List<Role> roleList = helloWorld.getRoleByUser(user);
34         for(Role role : roleList){
35             System.out.println(role.getId()+" , "+role.getRoleName());
36         }*/
37         MyRoleArray array = helloWorld.getRoles();
38         List<MyRole> roleList = array.item;
39         for(int i=0;i<roleList.size();i++){
40             MyRole mr = roleList.get(i);
41             System.out.println(mr.key+":");
42             for(Role r: mr.getValue()){
43                 System.out.println(r.getId()+","+r.getRoleName()+" ");
44             }
45             System.out.println();
46         }
47     }
48 }

这样就完整了自定义拦截器实现权限认证;先运行Server类,和以前一样;

客户端日志打印:

服务端日志信息:

假如我们把  client.getOutInterceptors().add(new AddHeaderInterceptor("admin","123")); // 添加自定义拦截器

密码改成 123

然后运行Client类,会报错;用户名密码不正确。

时间: 2024-08-01 16:23:44

cxf添加拦截器应用的相关文章

WebService学习笔记-CXF添加拦截器

Webservice拦截器:在webservice请求过程中,动态操作请求和响应的数据 分类 按照所处的位置分:服务器端拦截器  客户端拦截器 按照消息的方向分:入拦截器  出拦截器 按照定义者分:系统拦截器 自定义拦截器 在服务器端添加拦截器 package com.demo; //注意引入的类一定要正确 import javax.xml.ws.Endpoint; import org.apache.cxf.interceptor.LoggingInInterceptor; import or

Webservice:CXF添加拦截器实现权限控制

上一遍简单介绍了webservice和写了简单的cxf入门小程序 地址:http://blog.csdn.net/cjaver/article/details/38777057 接下来介绍一个比较实用的拦截器,可以进行权限控制等. 首先对于 一个 webservice来说 服务器端 : 有输入有输出(soap) 客户端: 同上 所以对于添加拦截器来说,也是有 In 拦截器 跟 Out拦截器 这里简单写一个服务器端的 In拦截器(控制发送过来的消息必须有 用户名,密码,所以添加的In拦截器) pu

使用CXF为webservice添加拦截器

拦截器分为Service端和Client端 拦截器是在发送soap消息包的某一个时机拦截soap消息包,对soap消息包的数据进行分析或处理.分为CXF自带的拦截器和自定义的拦截器 1.Service端: 通过将org.apache.cxf.jaxws.EndpointImpl类的方法即可实现   发布Web Service 方法可以通过Endpoint.publish()方法,此方法返为EndpointImpl,所以为Service端添加拦截器很简单. 部分代码: UserService us

WebService学习笔记-CXF添加自定义拦截器

使用自定义拦截器实现用户名和密码的校验 客户端:出拦截器 服务器:入拦截器 客户端 AddUserInterceptor.java package com.demo.interceptors; import java.util.List; import javax.xml.namespace.QName; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.headers.Header; import org

spring boot 添加拦截器

构建一个spring boot项目. 添加拦截器需要添加一个configuration @Configuration @ComponentScan(basePackageClasses = Application.class, useDefaultFilters = true) public class ServletContextConfig extends WebMvcConfigurationSupport { 为了方便扫描位置,我们可以写一个接口或者入口类Application放置于最外

CXF 自定义拦截器

------要想添加一个拦截器,目的是调用之前做一个认证,也就是说不是所有的请求都能调用,这样就可以验证了,更安全. 1     在服务端写一个拦截器,public class MyInterceptor extends AbstractPhaseInterceptor<SoapMessage>  ,要给一个构造方法(可以确定是什么时候执行这个拦截器,Phase.PRE_INVOKE就是调用之前执行),重写handleMessage方法,因为信息在请求头里面,所以这个方法中有一些解析XML的A

Apache CXF自定义拦截器

为什么设计拦截器?1.为了在webservice请求过程中,能动态操作请求和响应数据,CXF设计了拦截器 拦截器分类: 1.按所处的位置分:服务器端拦截器,客户端拦截器. 2.按消息的方向分:入拦截器,出拦截器. 3.按定义者分:系统拦截器,自定义拦截器. 客户端添加日志拦截器 package com.client.interceptor; import java.util.List; import javax.xml.namespace.QName; import org.apache.cxf

学习webservice之cxf(6):cxf日志拦截器

在Client服务中的pom.xml文件中添加依赖 <dependencies> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>3.2.5</version> </dependency> <dependency> <grou

CXF通过拦截器修改请求报文

最近一位做Siebel的同事需要通过Web Service接口调用另外一个系统,对方的Web Service使用的是CXF框架,并提供了WSDL文件. Siebel通过WSDL生成请求报文时报错,而直接通过SoapUI导入WSDL测试是OK的.通过抓取报文发现,两者生成的报文namespace有所不同,Siebel生成的namespace放在节点上,SoapUI生成的namespace放在头上,具体如下: Siebel生成的报文: <SOAP-ENV:Envelope xmlns:SOAP-EN