(六)CXF之自定义拦截器
一、需求分析
- 客户端在调用服务端的方法时,需要进行用户名和密码验证。此时分为:
- 客户端请求的时候,要发送用户名密码到服务端
- 服务端检验用户名密码。
二、案例
- 前提:本章案例是基于前一章节的例子进一步讲解自定义拦截器
2.1 服务端
- 发布服务
ublic class PublishMain { public static void main(String[] args) { String address="http://localhost:3333/login"; JaxWsServerFactoryBean factoryBean=new JaxWsServerFactoryBean(); factoryBean.setAddress(address); factoryBean.setServiceClass(ILogin.class); factoryBean.setServiceBean(new Login()); /** * // 添加in拦截器 日志拦截器 * // 添加out拦截器 日志拦截器 */ factoryBean.getInInterceptors().add(new LoggingInInterceptor());// 添加in拦截器 日志拦截器 factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); 添加out拦截器 日志拦截器 /** * 添加自定义拦截器,验证客户端发送的用户名和密码 */ factoryBean.getInInterceptors().add(new MyLoginInteceptor()); factoryBean.create(); System.out.println("服务发布......."); } }
-
factoryBean.getInInterceptors().add(new MyLoginInteceptor()); 在接收SOAP消息的时候,会执行LoggingInInterceptor日志拦截器和
自定义的 MyLoginInteceptor拦截器,该拦截器用于验证soap消息中的用户名和密码的合法性。
-
编写自定义的拦截器类
package com.shyroke.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 MyLoginInteceptor extends AbstractPhaseInterceptor<SoapMessage> { public MyLoginInteceptor() { /** * Phase.PRE_INVOKE 在调用方法之前调用自定拦截器 */ super(Phase.PRE_INVOKE); } @SuppressWarnings("null") public void handleMessage(SoapMessage message) throws Fault { List<Header> headers = message.getHeaders(); if (headers == null && headers.size() == 0) { throw new Fault(new IllegalArgumentException("没有Header,拦截器实施拦截")); } Header header = headers.get(0); Element ele = (Element) header.getObject(); NodeList uList = ele.getElementsByTagName("userName"); NodeList pList = ele.getElementsByTagName("passWord"); if (uList.getLength() != 1) { throw new Fault(new IllegalArgumentException("用户名格式不对")); } if (pList.getLength() != 1) { throw new Fault(new IllegalArgumentException("密码格式不对")); } String userName = uList.item(0).getTextContent(); String passWord = pList.item(0).getTextContent(); if (!userName.equals("admin") || !passWord.equals("123")) { throw new Fault(new IllegalArgumentException("用户名或者密码错误!")); } } }
- 其他代码与上一章节相同,本文省略。
2.2 客户端
- client.java
package com.shyroke.service; import java.util.List; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import com.shyroke.interceptor.MyHeaderInterceptor; public class Client { public static void main(String[] args) { ILogin login=new ILoginService().getILoginPort(); org.apache.cxf.endpoint.Client client=ClientProxy.getClient(login); /** * LoggingInInterceptor该拦截器类会在客户端被调用前打印日志 * LoggingOutInterceptor该拦截器类会在客户端被调用后打印日志 */ client.getInInterceptors().add(new LoggingInInterceptor()); client.getOutInterceptors().add(new LoggingOutInterceptor()); /** * 客户端请求服务端的方法的时候要先加用户名密码以供服务端验证 */ client.getOutInterceptors().add(new MyHeaderInterceptor("admin1","123")); MyRoleArray roles=login.getRoles(); List<MyRole> roleList= roles.item; for(MyRole role:roleList) { System.out.println(role.getKey()); for(Role r:role.getValue()) { System.out.println(r.getId()+"\t"+r.getRoleName()); } System.out.println("------------------"); } } }
-
client.getOutInterceptors().add(new MyHeaderInterceptor("admin1","123")) 客户端在请求服务单的方法时,会发送SOAP消息,就会先执行MyHeaderInterceptor
日志拦截器和自定义拦截器MyHeaderInterceptor,该拦截器用于发送在发送的SOAP消息中添加用户名密码等验证信息,以供服务端接收并验证。
- MyHeaderInterceptor.java
package com.shyroke.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 MyHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage> { private String userName; private String passWord; public MyHeaderInterceptor(String userName, String passWord) { /** * Phase.PREPARE_SEND 准备发送SOAP消息的时候调用拦截器 */ super(Phase.PREPARE_SEND); this.userName = userName; this.passWord = passWord; } public void handleMessage(SoapMessage message) throws Fault { List<Header> headerList = message.getHeaders(); Document doc = DOMUtils.createDocument(); Element ele = doc.createElement("LoginHeader"); Element uElement = doc.createElement("userName"); uElement.setTextContent(userName); Element pElement = doc.createElement("passWord"); pElement.setTextContent(passWord); ele.appendChild(uElement); ele.appendChild(pElement); headerList.add(new Header(new QName("http://com.shyroke"), ele)); } }
- 结果:
- 可知,服务端拦截器是生效的。
服务端代码在: 点击
客户端代码在: 点击