打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
spring boot-实现WebService(CXF实现)的拦截器(Interceptor)
userphoto

2017.10.25 广东

关注
  拦截器(Interceptor)是CXF功能最主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加很多功能。拦截器和JAX-WS Handler、Filter的功能类似,当服务被调用时,就会创建一个拦截器链(Interceptor Chain),拦截器链在服务输入(IN)或输出(OUT)阶段实现附加功能。

拦截器可以在客户端,也可以在服务端添加。当客户端发起一个WebService请求时,在客户端会创建输出拦截器链(outinterceptor),服务端接收到客户端的后,会创建输入拦截器链(ininterceptor)。当服务端返回响应消息时,响应消息会经过服务端的输出拦截链,客户端接收到服务端的响应时,会创建输入拦截器链,响应消息先经过输入拦截器链处理。拦截器在服务端和客户端的作用如图所示。

注:上图来源于网络。

下面,我们以一个Header认证为例,来演示CXF的拦截器的使用。

1、客户端拦截器

  1. public class ClientAuthorInterceptor extends AbstractPhaseInterceptor<SoapMessage> {  
  2.   
  3.     /** 
  4.      * 客户端申请的token信息 
  5.      */  
  6.     private String token;  
  7.       
  8.     public ClientAuthorInterceptor(String token) {  
  9.         // 设置拦截器的时机,在发送请求到服务端之前进行拦截  
  10.         super(Phase.PREPARE_SEND);  
  11.         this.token = token;  
  12.     }  
  13.   
  14.     @Override  
  15.     public void handleMessage(SoapMessage soap) throws Fault {  
  16.      // 在soap消息中添加认证头信息  
  17.      List<Header> headers = soap.getHeaders();  
  18.         Document doc = DOMUtils.createDocument();  
  19.         Element auth = doc.createElement(AuthorHeader.HEADER_NAME);  
  20.         Element token = doc.createElement(AuthorHeader.HEADER_TOKEN);  
  21.         token.setTextContent(this.token);  
  22.         auth.appendChild(token);  
  23.         Header header = new SoapHeader(new QName(AuthorHeader.HEADER_NAME), auth);  
  24.         headers.add(header);  
  25.     }  
  26. }  
注意:客户端是outinterceptor

2、服务端拦截器

下面,服务端对发送的消息进行拦截,并做认证

  1. @Slf4j  
  2. @Component  
  3. public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {  
  4.   
  5.     @Autowired  
  6.     private AuthorizationRepository repository;  
  7.   
  8.     public AuthInterceptor() {  
  9.         super(Phase.USER_LOGICAL);  
  10.     }  
  11.   
  12.     @Override  
  13.     public void handleMessage(SoapMessage message) throws Fault {  
  14.         Header header = message.getHeader(new QName("authrity"));  
  15.         if(null == header){  
  16.             log.warn("token没有认证通过!原因为:客户端请求中不存在认证的Header");  
  17.             throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中不存在认证的Header"));  
  18.         }  
  19.         Element ele = (Element) header.getObject();  
  20.         if(null == ele){  
  21.             log.warn("token没有认证通过!原因为:客户端请求中认证的Header无认证信息");  
  22.             throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的Header无认证信息"));  
  23.         }  
  24.         Node node = ele.getFirstChild();  
  25.         if(null == node){  
  26.             log.warn("token没有认证通过!原因为:客户端请求中认证的Header无认证信息");  
  27.             throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的Header无认证信息"));  
  28.         }  
  29.         String token = node.getTextContent();  
  30.         if(null == token || token.isEmpty()){  
  31.             log.warn("token没有认证通过!原因为:客户端请求中认证的Header无token信息");  
  32.             throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的Header无token信息"));  
  33.         }  
  34.         Authorization auth = repository.findByToken(token);  
  35.         if(null == auth){  
  36.             log.warn("token没有认证通过!原因为:客户端请求中认证的token信息无效,请查看申请流程中的正确token信息");  
  37.             throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中认证的token信息无效,请查看申请流程中的正确token信息,流程申请地址:http://127.0.0.1:8080/email"));  
  38.         }  
  39.         log.info("客户端认证成功,token有效!");  
  40.     }  
  41. }  
注:服务端为ininterceptor

编写拦截器很简单,只需继承AbstractPhaseInterceptor类并实现handleMessage即可。

3、spring boot配置拦截器,并发布服务

  1. @Configuration  
  2. public class WebserviceConfig {  
  3.     @Autowired  
  4.     private EmailService emailService;  
  5.       
  6.     @Autowired  
  7.     private AuthInterceptor interceptor;  
  8.       
  9.     @Autowired  
  10.     private ValidateInterceptor validateInterceptor;  
  11.       
  12.     @Bean(name = Bus.DEFAULT_BUS_ID)  
  13.     public SpringBus springBus() {  
  14.         return new SpringBus();  
  15.     }  
  16.   
  17.     /** 
  18.      * attention: 
  19.      * Details:发布WebService服务 
  20.      * @author chhliu 
  21.      * 创建时间:2017年5月22日 上午11:30:08 
  22.      * @return 
  23.      * Endpoint 
  24.      */  
  25.     @Bean  
  26.     public Endpoint endpoint() {  
  27.         EndpointImpl endPoint = new EndpointImpl(springBus(), emailService);  
  28.         endPoint.publish("/eamil");  
  29.         endPoint.getInInterceptors().add(interceptor); // 添加Header认证拦截器  
  30.         endPoint.getInInterceptors().add(validateInterceptor);// 添加消息格式校验拦截器  
  31.         return endPoint;  
  32.     }  
  33. }  
4、拦截器的Phase

Phase用来控制拦截器的工作时机,目前CXF支持的Phase如下:

  1. public static final String SETUP = "setup";// 设置阶段  
  2.     public static final String SETUP_ENDING = "setup-ending"; // 设置完之后  
  3.     public static final String PRE_LOGICAL = "pre-logical";// 程序对象编码  
  4.     public static final String PRE_LOGICAL_ENDING = "pre-logical-ending";  
  5.     public static final String USER_LOGICAL = "user-logical";  
  6.     public static final String USER_LOGICAL_ENDING = "user-logical-ending";  
  7.     public static final String POST_LOGICAL = "post-logical";  
  8.     public static final String POST_LOGICAL_ENDING = "post-logical-ending";  
  9.     public static final String PRE_MARSHAL = "pre-marshal";  
  10.     public static final String MARSHAL = "marshal";  
  11.     public static final String POST_MARSHAL = "post-marshal";  
  12.     public static final String MARSHAL_ENDING = "marshal-ending";  
  13.     public static final String PRE_PROTOCOL = "pre-protocol";  
  14.     public static final String PRE_PROTOCOL_FRONTEND = "pre-protocol-frontend";  
  15.     public static final String PRE_PROTOCOL_ENDING = "pre-protocol-ending";  
  16.     public static final String USER_PROTOCOL = "user-protocol";  
  17.     public static final String USER_PROTOCOL_ENDING = "user-protocol-ending";  
  18.     public static final String POST_PROTOCOL = "post-protocol";  
  19.     public static final String POST_PROTOCOL_ENDING = "post-protocol-ending";  
  20.     public static final String PREPARE_SEND = "prepare-send";  
  21.     public static final String PREPARE_SEND_ENDING = "prepare-send-ending";  
  22.     public static final String PRE_STREAM = "pre-stream";  
  23.     public static final String PRE_STREAM_ENDING = "pre-stream-ending";  
  24.     public static final String USER_STREAM = "user-stream";  
  25.     public static final String USER_STREAM_ENDING = "user-stream-ending";  
  26.     public static final String POST_STREAM = "post-stream";  
  27.     public static final String POST_STREAM_ENDING = "post-stream-ending";  
  28.     public static final String WRITE = "write";  
  29.     public static final String WRITE_ENDING = "write-ending";  
  30.     public static final String SEND = "send";  
  31.     public static final String SEND_ENDING = "send-ending";  
  32.      
  33.     public static final String RECEIVE = "receive"; // 接收阶段,传输层处理  
  34.     public static final String READ = "read";// SOAPHeader读取  
  35.     public static final String PROTOCOL = "protocol";// 协议处理阶段,例如JAX-WS的Handler处理  
  36.     public static final String PRE_UNMARSHAL = "pre-unmarshal";// SOAP请求解码之前  
  37.     public static final String UNMARSHAL = "unmarshal";// SOAP请求解码阶段  
  38.     public static final String POST_UNMARSHAL = "post-unmarshal"; // SOAP请求解码之后  
  39.     public static final String PRE_INVOKE = "pre-invoke"; // 调用业务处理之前进入该阶段  
  40.     public static final String INVOKE = "invoke"; // 调用业务阶段  
  41.     public static final String POST_INVOKE = "post-invoke";// 业务调用之后  
以下是ininterceptor定义的Phase

Phase

Functions

RECEIVE

Transport level processing

(PRE/USER/POST)_STREAM

Stream level processing/transformations

READ

This is where header reading typically occurs.

(PRE/USER/POST)_PROTOCOL

Protocol processing, such as JAX-WS SOAP handlers

UNMARSHAL

Unmarshalling of the request

(PRE/USER/POST)_LOGICAL

Processing of the umarshalled request

PRE_INVOKE

Pre invocation actions

INVOKE

Invocation of the service

POST_INVOKE

Invocation of the outgoing chain if there is one

以下是outintercptor定义的Phase

On the outgoing chain there are the following phases:

Phase

Functions

SETUP

Any set up for the following phases

(PRE/USER/POST)_LOGICAL

Processing of objects about to marshalled

PREPARE_SEND

Opening of the connection

PRE_STREAM

 

PRE_PROTOCOL

Misc protocol actions.

WRITE

Writing of the protocol message, such as the SOAP Envelope.

MARSHAL

Marshalling of the objects

(USER/POST)_PROTOCOL

Processing of the protocol message.

(USER/POST)_STREAM

Processing of the byte level message

SEND

 

在SEND Phase后,有一堆以*_ENDING Phase以及与之对应的Phase,例如SEND和SEND_ENDING,这类以ENDING结尾的Phase允许清理和关闭与之对应的Phase打开或启动的任何资源。

通过上面的示例,可以发现,CXF的拦截器可以为我们实现很多的附加功能。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)
「后端」网络编程与通信原理
【项目实践】一文带你搞定Session和JWT的登录认证方式
PHP方式实现jwt 方式用户身份认证
Android蓝牙通信
用Java来实现的Sniffer
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服