CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)
程序员文章站
2022-03-02 13:13:12
...
下面具体的webservice实现类直接用的是上面的,这里不再说明
CXF拦截器使用,创建一个使用SOAPHeader的安全验证 xml格式: <soap:Header> <auth:authentication xmlns:auth="http://gd.chinamobile.com//authentication"> <auth:systemID>1</auth:systemID> <auth:userID>test</auth:userID> <auth:password>test</auth:password> </auth:authentication> </soap:Header> 一,首先在服务端创建一个拦截器(被调用端),需要继承org.apache.cxf.phase.AbstractPhaseInterceptor 代码如下: import java.util.List; import javax.xml.soap.SOAPException; import org.apache.cxf.binding.soap.SoapHeader; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.headers.Header; import org.apache.cxf.helpers.XMLUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public class AuthIntercetpr extends AbstractPhaseInterceptor<SoapMessage> { private static final Logger logger = Logger.getLogger(AuthIntercetpr.class); public static final String xml_namespaceUR_att = "http://gd.chinamobile.com//authentication"; public static final String xml_header_el = "soap:Header"; public static final String xml_authentication_el = "auth:authentication"; public static final String xml_systemID_el = "auth:systemID"; public static final String xml_userID_el = "auth:userID"; public static final String xml_password_el = "auth:password"; public AuthIntercetpr() { // 指定该拦截器在哪个阶段被激发 super(Phase.PRE_INVOKE); } // 处理消息 public void handleMessage(SoapMessage message) { logger.info("==================SoapMessage =" + message); // 获取SOAP消息的全部头 List<Header> headers = message.getHeaders(); if (null == headers || headers.size() < 1) { throw new Fault(new SOAPException("SOAP消息头格式不对哦!")); } for (Header header : headers) { SoapHeader soapHeader = (SoapHeader) header; // 取出SOAP的Header元素 Element element = (Element) soapHeader.getObject(); logger.info("ELEMENT =" + element.toString()); XMLUtils.printDOM(element); NodeList userIdNodes = element .getElementsByTagName(xml_userID_el); NodeList pwdNodes = element .getElementsByTagName(xml_password_el); NodeList systemIdNodes = element .getElementsByTagName(xml_systemID_el); logger.info("############ 打印帐号信息 ##############"); logger.info(userIdNodes.item(0) + "=" + userIdNodes.item(0).getTextContent()); logger.info(systemIdNodes.item(0) + "=" + systemIdNodes.item(0).getTextContent()); logger.info(pwdNodes.item(0) + "=" + pwdNodes.item(0).getTextContent()); logger.info("############————————##############"); if (null != userIdNodes && userIdNodes.item(0).getTextContent().equels("test") ) { if (null != pwdNodes && pwdNodes.item(0).getTextContent().equals("test")) { logger.info("$$$$$$$$ 认证成功"); } else {//认证失败则抛出异常,停止继续操作 SOAPException soapExc = new SOAPException("阁下可能不是合法用户!"); throw new Fault(soapExc); } } else {//认证失败则抛出异常,停止继续操作 SOAPException soapExc = new SOAPException("阁下可能不是合法用户!"); throw new Fault(soapExc); } } } } 二,修改cxf-beans.xml <!--id:随意配,implementor:指定接口具体实现类,address:随意配,访问时会用到,下面会做说明--> <!--拦截器--> <bean id="authIntercetpr" class="unitTest.AuthIntercetpr"></bean> <jaxws:endpoint id="HelloWorldService" implementor="com.ws.HelloWorldServiceImpl" address="/IHelloService"> <!-- 在此配置调用当前ws所触发的拦截器--> <jaxws:inInterceptors><ref bean="authIntercetpr" /></bean> <!--或者直接在这里写<bean class="unitTest.AuthIntercetpr"></bean>--> </jaxws:inInterceptors> </jaxws:endpoint> 到此服务端工作完毕!!! 下面是客户端(调用端) 三,这边同样创建一个拦截器,实现org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.xml.namespace.QName; import org.apache.cxf.binding.soap.SoapHeader; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor; import org.apache.cxf.headers.Header; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.helpers.XMLUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.Phase; import org.w3c.dom.Document; import org.w3c.dom.Element; public class AddSoapHeader extends AbstractSoapInterceptor { public static final String xml_namespaceUR_att = "http://gd.chinamobile.com//authentication"; public static final String xml_header_el = "soap:Header"; public static final String xml_authentication_el = "auth:authentication"; public static final String xml_systemID_el = "auth:systemID"; public static final String xml_userID_el = "auth:userID"; public static final String xml_password_el = "auth:password"; public AddSoapHeader() { // 指定该拦截器在哪个阶段被激发 super(Phase.WRITE); } public void handleMessage(SoapMessage message) throws Fault { SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); String time = sd.format(date); String userId = "test"; String sysId = "1"; String password = "test"; QName qname = new QName("RequestSOAPHeader");//这个值暂时不清楚具体做什么用,可以随便写 Document doc = (Document) DOMUtils.createDocument(); Element root = doc.createElement(xml_header_el); Element eSysId = doc.createElement(xml_systemID_el); eSysId.setTextContent(sysId); Element eUserId = doc.createElement(xml_userID_el); eUserId.setTextContent(userId); Element ePwd = doc.createElement(xml_password_el); ePwd.setTextContent(password); Element child = doc.createElementNS(xml_namespaceUR_att, xml_authentication_el); child.appendChild(eSysId); child.appendChild(eUserId); child.appendChild(ePwd); root.appendChild(child); XMLUtils.printDOM(root);// 只是打印xml内容到控制台,可删除 SoapHeader head = new SoapHeader(qname, root); List<Header> headers = message.getHeaders(); headers.add(head); } } 四,具体调用ws的类代码 private static final String webServiceConTimeout = "6000"; private static final String webServiceRevTimeout = "6000"; 。。。。。。。 HelloWorldServiceImplService hello = new HelloWorldServiceImplService(); HelloWorldService service = hello.getHelloWorldServiceImplPort(); //以上什么意思请参考:http://learning.iteye.com/admin/blogs/1333223 Client clientProxy = ClientProxy.getClient(service);//通过目标ws获取代理 //注入拦截器,getOutInterceptors代表调用服务端时触发,getInInterceptors就是被调用才触发 clientProxy.getOutInterceptors().add(ash); // 超时时间设置 HTTPConduit http = (HTTPConduit) clientProxy.getConduit(); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setConnectionTimeout(Integer .valueOf(webServiceConTimeout)); httpClientPolicy.setReceiveTimeout(Integer .valueOf(webServiceRevTimeout)); httpClientPolicy.setAllowChunking(false); http.setClient(httpClientPolicy); //以上插入点超时设置方式 //下面这行代码是具体调用服务段的deleteTeskTask() CallResult cResult = service.deleteTeskTask("1223"); 。 。 客户端代码到此结束 五,还有一种方式是通过JaxWsProxyFactoryBean方式,注册拦截器及实例化ws,代码如下: private static final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); AddSoapHeader ash = new AddSoapHeader(); ArrayList list = new ArrayList(); // 添加soap header 信息 list.add(ash); //注入拦截器,getOutInterceptors代表调用服务端时触发,getInInterceptors就是被调用才触发 factory.setOutInterceptors(list); factory.setServiceClass(HelloWorldService.class);//实例化ws factory.setAddress("http://xxx.xxx.xxx.xxx:8004/services/IHelloService"); Object obj = factory.create(); HelloWorldService service = (HelloWorldService) obj; //下面这行代码是具体调用服务段的deleteTeskTask() CallResult cResult = service.deleteTeskTask("1223"); ##########这段代码可替代步骤(四)##### 到此全部工作结束 具体一些概念还请自己baidu/google