拦截器(Interceptor)是CXF功能最主要的扩展点,可以在不对核心模块进行修改的情况下,动态添加很多功能。拦截器和JAX-WS Handler、Filter的功能类似,当服务被调用时,就会创建一个拦截器链(Interceptor Chain),拦截器链在服务输入(IN)或输出(OUT)阶段实现附加功能。
拦截器可以在客户端,也可以在服务端添加。当客户端发起一个WebService请求时,在客户端会创建输出拦截器链(outinterceptor),服务端接收到客户端的后,会创建输入拦截器链(ininterceptor)。当服务端返回响应消息时,响应消息会经过服务端的输出拦截链,客户端接收到服务端的响应时,会创建输入拦截器链,响应消息先经过输入拦截器链处理。拦截器在服务端和客户端的作用如图所示。
注:上图来源于网络。
下面,我们以一个Header认证为例,来演示CXF的拦截器的使用。
1、客户端拦截器
public class ClientAuthorInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
/**
* 客户端申请的token信息
*/
private String token;
public ClientAuthorInterceptor(String token) {
// 设置拦截器的时机,在发送请求到服务端之前进行拦截
super(Phase.PREPARE_SEND);
this.token = token;
}
@Override
public void handleMessage(SoapMessage soap) throws Fault {
// 在soap消息中添加认证头信息
List<Header> headers = soap.getHeaders();
Document doc = DOMUtils.createDocument();
Element auth = doc.createElement(AuthorHeader.HEADER_NAME);
Element token = doc.createElement(AuthorHeader.HEADER_TOKEN);
token.setTextContent(this.token);
auth.appendChild(token);
Header header = new SoapHeader(new QName(AuthorHeader.HEADER_NAME), auth);
headers.add(header);
}
}
注意:客户端是outinterceptor
2、服务端拦截器
下面,服务端对发送的消息进行拦截,并做认证
@Slf4j
@Component
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
@Autowired
private AuthorizationRepository repository;
public AuthInterceptor() {
super(Phase.USER_LOGICAL);
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
Header header = message.getHeader(new QName("authrity"));
if(null == header){
log.warn("token没有认证通过!原因为:客户端请求中不存在认证的Header");
throw new Fault(new AuthenticationException("token没有认证通过!原因为:客户端请求中不存在认证的Header"));
}
Element ele = (Element) header.getObject();
if(null == ele){
log.warn("token没有认证通过!原因为:客户端请求中认证的Header无认证信息");
throw new Fa