CXF已经内置了一些拦截器,这些拦截器大部分默认添加到拦截器链中,有些拦截器也可以手动添加,如手动添加CXF提供的日志拦截器。也可以自定义拦截器,CXF中实现自定义拦截器很简单,只要继承AbstractPhaseInterceptor或者AbstractPhaseInterceptor的子类(如AbstractSoapInterceptor)即可。
自定义权限认证拦截器
权限认证拦截器处理SOAPHeader中的认证信息,客户端在发起请求时在SOAPHeader中添加认证信息,服务端在接收到请求后,校验认证信息,校验通过则继续执行,校验不通过则返回错误。
<!-- 认证信息格式如下 --> <auth xmlns="http://www.tmp.com/auth"> <name>admin</name> <password>admin</password> </auth>
服务端授权验证拦截器
package com.study.cxfspringdemo1.interceptor; 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; /** * 服务端输入拦截器 拦截请求有没有授权信息 * */ 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.hellocxfspring.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"> <!-- helloWS通过注解获取 --> <jaxws:endpoint id="helloWSEndpoint" implementor="#helloWS" address="/hello"> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> <bean class="com.study.cxfspringdemo1.interceptor.AuthValidateInterceptor"></bean> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </jaxws:outInterceptors> </jaxws:endpoint> </beans>
客户端添加授权拦截器
package com.study.cxfspringdemo1client.interceptor; 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; /** * 添加授权拦截器 用于在客户端发请求时添加授权 */ 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.hellocxfspring.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)); } }
CXF客户端
package com.study.cxfspringdemo1client; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import com.study.cxfspringdemo1client.interceptor.AuthAddInterceptor; /** * Hello world! * */ public class Client { public static void main(String[] args) { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(HelloWS.class); factory.setAddress("http://localhost:8080/cxfspringdemo1-0.0.1-SNAPSHOT/services/hello"); factory.getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor()); // 客户端授权拦截器 factory.getOutInterceptors().add(new AuthAddInterceptor()); factory.getOutInterceptors().add(new org.apache.cxf.interceptor.LoggingOutInterceptor()); HelloWS helloWS = factory.create(HelloWS.class); String welcome = helloWS.welcome("from interceptor cxf!"); System.out.println("result:" + welcome); } }
结果:
十一月 03, 2016 2:38:24 下午 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromClass 信息: Creating Service {http://www.hellocxfspring.com/services/hello}HelloWSService from class com.study.cxfspringdemo1client.HelloWS 十一月 03, 2016 2:38:25 下午 org.apache.cxf.services.HelloWSService.HelloWSPort.HelloWS 信息: Outbound Message --------------------------- ID: 1 Address: http://localhost:8080/cxfspringdemo1-0.0.1-SNAPSHOT/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:Header><auth xmlns="http://www.hellocxfspring.com/auth"><name>admin</name><password>admin</password></auth></soap:Header><soap:Body><ns2:welcome xmlns:ns2="http://www.hellocxfspring.com/services/hello"><name>from interceptor cxf!</name></ns2:welcome></soap:Body></soap:Envelope> -------------------------------------- 十一月 03, 2016 2:38:31 下午 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, 03 Nov 2016 06:38:31 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.hellocxfspring.com/services/hello"><return>Server say welcome:from interceptor cxf!</return></ns2:welcomeResponse></soap:Body></soap:Envelope> -------------------------------------- result:Server say welcome:from interceptor cxf!
CXF日志拦截器
CXF提供了输入日志拦截器LoggingInInterceptor和输出日志拦截器LoggingOutInterceptor,日志拦截器可以用在服务端也可以用在客户端。在测试或者调试的时候,可以用日志拦截器输出服务端、客户端请求和接收到的信息。
服务端日志内容
七月 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> --------------------------------------
客户端日志内容
七月 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> --------------------------------------