【WebService框架-CXF】——CXF拦截器
来源:互联网 发布:耐克淘宝官方旗舰店 编辑:程序博客网 时间:2024/06/05 14:07
背景
当一个服务发布之后,只要有服务地址,我们就可以建立客户端对服务进行调用。如果服务的提供者想要对可以调用服务的客户端进行限制,如:只有某些客户可以调用此服务。这时候就会用到拦截器,来进行权限控制。
明白了拦截器的应用场景,我们看看CXF的拦截器怎么用。
IN&OUT拦截器
从图中我们可以总结出,只要从一端发出消息时要进行拦截,就要使用OUT拦截器。如果要对接收的消息进行拦截就要使用IN拦截器。
在服务端添加IN拦截器和OUT拦截器
public class TestMain { public static void main(String[] arg){ HelloWorld hw=new HelloWorldWS(); EndpointImpl eImpl=(EndpointImpl)Endpoint.publish("http://localhost:9009/HelloWorldWS", hw); eImpl.getInInterceptors().add(new LoggingInInterceptor()); eImpl.getOutInterceptors().add(new LoggingOutInterceptor()); System.out.println("Web Service暴露成功!"); }}
调用客户端,之后在服务端查看打印结果
Inbound Message
通过LoggingInInterceptor()拦截到的信息
六月 18, 2016 9:18:40 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log信息: Inbound Message----------------------------ID: 3Address: http://localhost:9009/HelloWorldWSEncoding: UTF-8Http-Method: POSTContent-Type: text/xml; charset=UTF-8Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[185], content-type=[text/xml; charset=UTF-8], Host=[localhost:9009], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 2.4.0]}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://ws.tgb.com/"><arg0>许晨阳</arg0></ns2:sayHi></soap:Body></soap:Envelope>
Outbound Message
通过LoggingOutInterceptor()拦截到的信息
六月 18, 2016 9:18:40 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log信息: Outbound Message---------------------------ID: 3Encoding: UTF-8Content-Type: text/xmlHeaders: {}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHiResponse xmlns:ns2="http://ws.tgb.com/"><return>许晨阳,你好!现在时间是:2016-06-18 09:18:40</return></ns2:sayHiResponse></soap:Body></soap:Envelope>
在客户端添加IN拦截器和OUT拦截器
此时相同的信息会在客户端打印出来。
public class ClientMain { public static void main(String[] args){ //工厂,继承Service HelloWorldWS factory=new HelloWorldWS(); //只是服务的代理 HelloWorld hw=factory.getHelloWorldWSPort(); //客户端拦截器 Client c= ClientProxy.getClient(hw); c.getInInterceptors().add(new LoggingInInterceptor()); c.getOutInterceptors().add(new LoggingOutInterceptor()); System.out.println(hw.sayHi("许晨阳")); }}
--------------------------------------六月 20, 2016 5:33:43 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log信息: Outbound Message---------------------------ID: 1Address: http://localhost:9009/HelloWorldWSEncoding: UTF-8Content-Type: text/xmlHeaders: {Accept=[*/*], SOAPAction=[""]}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHi xmlns:ns2="http://ws.tgb.com/"><arg0>许晨阳</arg0></ns2:sayHi></soap:Body></soap:Envelope>
--------------------------------------六月 20, 2016 5:33:43 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log信息: Inbound Message----------------------------ID: 1Response-Code: 200Encoding: UTF-8Content-Type: text/xml;charset=UTF-8Headers: {Content-Length=[252], content-type=[text/xml;charset=UTF-8], Server=[Jetty(7.3.1.v20110307)]}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHiResponse xmlns:ns2="http://ws.tgb.com/"><return>许晨阳,你好!现在时间是:2016-06-20 05:33:43</return></ns2:sayHiResponse></soap:Body></soap:Envelope>
自定义拦截器
通过自定义拦截器,我们可以根据需求修改SOAP消息,进行权限控制。
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public AuthInterceptor(String phase) { super(phase); } @Override public void handleMessage(SoapMessage soapMessage) throws Fault { List<Header> headers=soapMessage.getHeaders(); if(headers==null || headers.size()<1){ throw new Fault(new IllegalArgumentException("没有Header,不能调用")); } Header firstHeader=headers.get(0); Element ele=(Element)firstHeader.getObject(); NodeList userIds=ele.getElementsByTagName("userId"); NodeList pwds=ele.getElementsByTagName("pwd"); if(userIds==null || userIds.getLength()!=1){ throw new Fault(new IllegalArgumentException("用户名格式不对!")); } if(pwds==null || pwds.getLength()!=1){ throw new Fault(new IllegalArgumentException("密码格式不对!")); } String userId=userIds.item(0).getTextContent(); String pwd=pwds.item(0).getTextContent(); if(!userId.equals("1") ||!pwd.equals("123")){ throw new Fault(new IllegalArgumentException("用户名和密码不对!")); } }}
在这个拦截器中,首先判断是SOAP消息中是否有Header,如果有,再判断用户名和密码是否正确。
此时,要将自定义的拦截器添加到InInterceptors,并传入一个Phase的字符串参数。
public class TestMain { public static void main(String[] arg){ HelloWorld hw=new HelloWorldWS(); //hw.sayHi("许晨阳"); EndpointImpl eImpl=(EndpointImpl)Endpoint.publish("http://localhost:9009/HelloWorldWS", hw); eImpl.getInInterceptors().add(new LoggingInInterceptor()); eImpl.getOutInterceptors().add(new LoggingOutInterceptor()); //自定义拦截器 eImpl.getInInterceptors().add(new AuthInterceptor(Phase.PRE_INVOKE)); System.out.println("Web Service暴露成功!"); }}
此时,如果客户端直接调用,会无法调用。
六月 20, 2016 5:51:24 下午 org.apache.cxf.interceptor.AbstractLoggingInterceptor log信息: Inbound Message----------------------------ID: 1Response-Code: 500Encoding: UTF-8Content-Type: text/xml;charset=UTF-8Headers: {Content-Length=[222], content-type=[text/xml;charset=UTF-8], Server=[Jetty(7.3.1.v20110307)]}Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>没有Header,不能调用</faultstring></soap:Fault></soap:Body></soap:Envelope>--------------------------------------Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: 没有Header,不能调用 at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:146) at com.sun.proxy.$Proxy23.sayHi(Unknown Source) at com.tgb.ws.ClientMain.main(ClientMain.java:27) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)Caused by: org.apache.cxf.binding.soap.SoapFault: 没有Header,不能调用
此时返回到客户端的SOAP消息为<soap:Fault>
。
所以我们要在客户端也添加拦截器将用户名和密码添加到SOAP消息的Header中。
public class AddHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> { private String userId; private String pwd; public AddHeaderInterceptor(String userId, String pwd) { super(Phase.PREPARE_SEND); this.userId=userId; this.pwd=pwd; } @Override public void handleMessage(SoapMessage soapMessage) throws Fault { List<Header> headers= soapMessage.getHeaders(); System.out.println(headers.size()); Document doc= DOMUtils.createDocument(); Element ele=doc.createElement("authHeader"); Element eleUser=doc.createElement("userId"); eleUser.setTextContent(userId); Element elePwd=doc.createElement("pwd"); elePwd.setTextContent(pwd); ele.appendChild(eleUser); ele.appendChild(elePwd); Header header=new Header(new QName("http://impl.ws.tgb.com/"),ele); headers.add(header); System.out.println(headers.size()); }}
public class ClientMain { public static void main(String[] args){ //工厂 HelloWorldWS factory=new HelloWorldWS(); //只是服务的代理 HelloWorld hw=factory.getHelloWorldWSPort(); //客户端拦截器 Client c= ClientProxy.getClient(hw); c.getInInterceptors().add(new LoggingInInterceptor()); c.getOutInterceptors().add(new AddHeaderInterceptor("1","123")); c.getOutInterceptors().add(new LoggingOutInterceptor()); System.out.println(hw.sayHi("许晨阳")); }}
需要注意的是,我们要把此拦截器添加到客户端的OutInterceptors,这个和服务端不一样。
总结
CXF拦截器可以让我们修改SOAP消息,并在此基础上对客户端进行权限控制,很方便。
0 0
- 【WebService框架-CXF】——CXF拦截器
- 【WebService框架-CXF】——CXF+Spring+自定义拦截器构建WebService服务端
- 【WebService框架-CXF】——CXF+Spring+Struts+自定义拦截器构建WebService客户端
- webservice框架CXF拦截器的使用
- webservice cxf 拦截器
- CXF 框架拦截器
- 【WebService框架-CXF】——WebService和CXF
- 【WebService框架-CXF】——CXF入门实例
- WebService CXF 中的拦截器(Interceptor)
- WebService学习笔记-CXF添加拦截器
- cxf+Spring的webservice应用--拦截器
- WebService(6)_Apache CXF拦截器
- WebService-CXF-Spring+自定义拦截器
- webservice利用cxf框架编写日志拦截器和自定义拦截器
- webservice应用 cxf框架
- WebService之CXF框架
- webservice的CXF框架
- webservice之cxf框架
- DX学习笔记(具有颜色的三角形)
- 重载类的特殊方法
- STUN和TURN技术浅析(二)
- Mac OS X 命令行安装Maven,异常处理
- MapReduce进阶:多路径输入输出
- 【WebService框架-CXF】——CXF拦截器
- 如何栽树梅派上搭建个人网站
- hdu3507(斜率dp)
- Android创建前台运行的Service
- django 静态资源共享
- 利用ViewPager做向导界面
- [Android] LayoutInflater 详解
- 在Arduino中添加第3方库
- zabbix 安装