CXF已经内置了一些拦截器,这些拦截器大部分默认加入到拦截器链中,有些拦截器也能够手动加入,如手动加入CXF提供的日志拦截器。也能够自己定义拦截器。CXF中实现自己定义拦截器非常easy。仅仅要继承AbstractPhaseInterceptor或者AbstractPhaseInterceptor的子类(如AbstractSoapInterceptor)就可以。
自己定义权限认证拦截器
权限认证拦截器处理SOAPHeader中的认证信息,client在发起请求时在SOAPHeader中加入认证信息,服务端在接收到请求后,校验认证信息,校验通过则继续运行,校验不通过则返回错误。
<!-- 认证信息格式例如以下 -->
<auth xmlns="http://www.tmp.com/auth">
<name>admin</name>
<password>admin</password>
</auth>
client加入授权拦截器
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* 加入授权拦截器
* 用于在client发请求时加入授权
* @author accountwcx@qq.com
*
*/
public class AuthAddInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public AuthAddInterceptor(){
//准备发送阶段
super(Phase.PREPARE_SEND);
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders();
Document doc = DOMUtils.createDocument();
//Element auth = doc.createElement("auth");
Element auth = doc.createElementNS("http://www.tmp.com/auth", "auth");
Element name = doc.createElement("name");
name.setTextContent("admin");
Element password = doc.createElement("password");
password.setTextContent("admin");
auth.appendChild(name);
auth.appendChild(password);
headers.add(new Header(new QName(""), auth));
}
}
服务端授权验证拦截器
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* 服务端输入拦截器
* 拦截请求有没有授权信息
* @author accountwcx@qq.com
*
*/
public class AuthValidateInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public AuthValidateInterceptor(){
super(Phase.PRE_INVOKE);
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders();
if(headers == null || headers.size() < 1) {
throw new Fault(new Exception("无授权信息。"));
}
Element auth = null;
//获取授权信息元素
for(Header header : headers){
QName qname = header.getName();
String ns = qname.getNamespaceURI();
String tagName = qname.getLocalPart();
if(ns != null && ns.equals("http://www.tmp.com/auth") && tagName != null && tagName.equals("auth")){
auth = (Element)header.getObject();
break;
}
}
//假设授权信息元素不存在。提示错误
if(auth == null){
throw new Fault(new Exception("无授权信息!"));
}
NodeList nameList = auth.getElementsByTagName("name");
NodeList pwdList = auth.getElementsByTagName("password");
if(nameList.getLength() != 1 || pwdList.getLength() != 1){
throw new Fault(new Exception("授权信息错误!"
));
}
String name = nameList.item(0).getTextContent();
String password = pwdList.item(0).getTextContent();
if(!"admin".equals(name) || !"admin".equals(password)){
throw new Fault(new Exception("授权信息错误。"));
}
}
}
服务端拦截器配置
<?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"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:endpoint id="helloWSEndpoint" implementor="#helloWS" address="/hello">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
<bean class="com.rvho.cxfserver.interceptor.AuthValidateInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:endpoint>
</beans>
client请求
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(HelloWS.class);
factory.setAddress("http://localhost:8280/cxfserver/services/hello");
factory.getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor());
//client授权拦截器
factory.getOutInterceptors().add(new com.rvho.cxfclient.interceptor.AuthAddInterceptor());
factory.getOutInterceptors().add(new org.apache.cxf.interceptor.LoggingOutInterceptor());
HelloWS helloWS = factory.create(HelloWS.class);
String welcome = helloWS.welcome("accountwcx@qq.com");
CXF日志拦截器
CXF提供了输入日志拦截器LoggingInInterceptor和输出日志拦截器LoggingOutInterceptor,日志拦截器能够用在服务端也能够用在client。在測试或者调试的时候。能够用日志拦截器输出服务端、client请求和接收到的信息。
服务端日志内容
七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Address: http://localhost:8280/cxfserver/services/hello
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], cache-control=[no-cache], connection=[keep-alive], Content-Length=[212], content-type=[text/xml; charset=UTF-8], host=[localhost:8280], pragma=[no-cache], SOAPAction=[""], user-agent=[Apache CXF 3.1.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcome xmlns:ns2="http://www.tmp.com/services/hello"><name>accountwcx@qq.com</name></ns2:welcome></soap:Body></soap:Envelope>
--------------------------------------
七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Outbound Message
---------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcomeResponse xmlns:ns2="http://www.tmp.com/services/hello"><return>欢迎使用CXF!accountwcx@qq.com</return></ns2:welcomeResponse></soap:Body></soap:Envelope>
--------------------------------------
client日志内容
七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Outbound Message
---------------------------
ID: 1
Address: http://localhost:8280/cxfserver/services/hello
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcome xmlns:ns2="http://www.tmp.com/services/hello"><name>accountwcx@qq.com</name></ns2:welcome></soap:Body></soap:Envelope>
--------------------------------------
七月 30, 2015 10:51:37 上午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-type=[text/xml;charset=UTF-8], Date=[Thu, 30 Jul 2015 02:51:37 GMT], Server=[Apache-Coyote/1.1], transfer-encoding=[chunked]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:welcomeResponse xmlns:ns2="http://www.tmp.com/services/hello"><return>欢迎使用CXF!accountwcx@qq.com</return></ns2:welcomeResponse></soap:Body></soap:Envelope>
--------------------------------------
欢迎使用CXF!accountwcx@qq.com