CXF与Spring集成:自定义验证权限以及日志记录

Spring配置文件:

<!-- 发布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) {
		}
	}
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值