CXF与Spring集成:自定义验证权限以及日志记录
2016-03-01 18:40
411 查看
Spring配置文件:
自定义拦截器验证用户信息实现
自定义拦截器记录日志,PS:可以用CXF本身的日志记录拦截器:
客户端发送过来的格式应如下:
补充: 自定义LoggingOutInterceptor
这部分纠结了很久,参考自 http://stackoverflow.com/questions/6438178/cxf-outgoing-interceptor-get-soap-response-body-that-is-always-null,
其实就是重现了源代码的方式。
<!-- 发布WebService服务(Spring配置文件中的配置) --> <jaxws:server id="xxWS" serviceClass="com.xx.xx" address="/xx"> <jaxws:serviceBean> <bean class="com.xx.xxImpl"></bean> </jaxws:serviceBean> <jaxws:inInterceptors> <bean class="com.xx.LoggingInterceptor"></bean> <bean class="com.xx.AuthInterceptor"></bean> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </jaxws:outInterceptors> </jaxws:server>
自定义拦截器验证用户信息实现
import java.util.List; import javax.xml.soap.SOAPException; 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.Node; public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public AuthInterceptor() { super(Phase.PRE_PROTOCOL); } @Override public void handleMessage(SoapMessage message) throws Fault { String user = null, passwd = null; List<Header> headers = message.getHeaders(); if (headers == null) { SOAPException soapEx = new SOAPException(Constant.ERROR_CODE_5001 + "::Authentication failed!"); throw new Fault(soapEx); } else { for (Header header : headers) { if (header == null) continue; Element element = (Element) header.getObject(); if (element == null) continue; Node node = element.getFirstChild(); if (node == null) continue; if (element.getNodeName().equals("user")) { user = node.getTextContent(); } if (element.getNodeName().equals("passwd")) { passwd = node.getTextContent(); } } } if (user == null || passwd == null) { SOAPException soapEx = new SOAPException(Constant.ERROR_CODE_5000 + "::Authentication failed!"); throw new Fault(soapEx); } // 验证用户名和密码是否正确... } }
自定义拦截器记录日志,PS:可以用CXF本身的日志记录拦截器:
org.apache.cxf.interceptor.LoggingInInterceptor替换配置文件中的
com.xx.LoggingInterceptor
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.IOUtils; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; import com.cabinet.eip.utils.StringUtils; public class LoggingInInterceptor extends AbstractPhaseInterceptor<SoapMessage> { private Logger logger = Logger.getLogger(LoggingInInterceptor.class); public LoggingInInterceptor() { super(Phase.RECEIVE); } public void setLoggerName(String loggerName) { this.logger = Logger.getLogger(loggerName); } public void setLogger(Logger logger) { this.logger = logger; } @Override public void handleMessage(SoapMessage message) { long logID = System.nanoTime(); InputStream is = null; try { // 用来记录当前报文的ID,为了日志里标识单次请求的所有日志 message.getExchange().put("LOG.SEQUENCE", logID); is = message.getContent(InputStream.class); String xml = IOUtils.toString(is, "UTF-8"); message.setContent(InputStream.class, new ByteArrayInputStream(xml.getBytes("UTF-8"))); if (xml == null || xml.equals("")) { return; } // StringUtils为自己写的用dom4j格式化xml,不格式化输出的内容是一行,这里不贴了,网上搜很多 xml = StringUtils.formatXML(xml, null); String httpMethod = (String) message.get(Message.HTTP_REQUEST_METHOD); StringBuilder info = new StringBuilder(); info.append("------接收到Soap报文(").append(logID).append("), httpMethod:").append(httpMethod).append(xml); logger.info(info.toString()); } catch (Exception e) { logger.error("CXF记录日志错误(" + logID + "): ", e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } } }
客户端发送过来的格式应如下:
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="xxx"> <soapenv:Header> <user>username</user> <passwd>加密后的密码</passwd> </soapenv:Header> <soapenv:Body> <!-- xx的名字为要调用的WebService方法名 --> <ws:xx> <!-- 实际调用的方法所传递的参数 --> </ws:xx> </soapenv:Body> </soapenv:Envelope>
补充: 自定义LoggingOutInterceptor
这部分纠结了很久,参考自 http://stackoverflow.com/questions/6438178/cxf-outgoing-interceptor-get-soap-response-body-that-is-always-null,
其实就是重现了源代码的方式。
org.apache.cxf.interceptor.LoggingOutInterceptor代码如下:
import java.io.OutputStream; import org.apache.commons.io.IOUtils; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.io.CacheAndWriteOutputStream; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.io.CachedOutputStreamCallback; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; public class LoggingOutInterceptor extends AbstractPhaseInterceptor<SoapMessage> { private Logger logger = Logger.getLogger(LoggingOutInterceptor.class); public LoggingOutInterceptor() { super(Phase.PRE_STREAM); } @Override public void handleMessage(SoapMessage message) { String logID = ""; try { // 获取之前声明的日志ID标识,单次请求输出的所有日志标识相同 Object obj = message.getExchange().get("LOG.SEQUENCE"); if (obj != null) logID = obj.toString(); OutputStream os = message.getContent(OutputStream.class); CacheAndWriteOutputStream cwos = new CacheAndWriteOutputStream(os); message.setContent(OutputStream.class, cwos); cwos.registerCallback(new LoggingOutCallBack(logID)); } catch (Exception e) { logger.error("CXF记录日志错误(" + logID + "): ", e); } } class LoggingOutCallBack implements CachedOutputStreamCallback { private String logID; public LoggingOutCallBack(String logID) { this.logID = logID; } @Override public void onClose(CachedOutputStream cos) { try { if (cos != null) { String xml = IOUtils.toString(cos.getInputStream()); if (xml == null || xml.equals("")) return; logger.info("------发出的Soap报文(" + logID + ")" + xml); } } catch (Exception e) { logger.error("CXF记录日志错误(" + logID + "): ", e); } try { cos.lockOutputStream(); cos.resetOut(null, false); } catch (IOException e) { } } @Override public void onFlush(CachedOutputStream arg0) { } } }
相关文章推荐
- JAVA_反射
- Spring框架中SecurityContextHolder类的使用详解(未完待续)
- Java入门 一些概念及类
- [java] JNLP文件安装
- 读java编程思想有感一
- Java中ArrayList和LinkedList区别 时间复杂度 与空间复杂度
- java类的加载顺序
- C#和Java区别
- Java中String转换Double类型 Java小数点后留两位
- eclipse里的Ctrl操作很慢
- Java 8读取Access数据库报错的问题——用32位Java 7
- Java关键字final、static使用总结
- JAVA基础---面向对象
- POJO TO Map
- Java泛型的实现原理
- JAVA-单例模式之性能探究
- Java多线程(七)——Collections.synchronizedXX包装器
- 交换两个整数类型的变量(不借助第3个变量)
- Struts项目环境配置
- 初学者必看——最简单最清晰的Struts2项目搭建流程