您的位置:首页 > 编程语言 > Java开发

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

2016-03-01 18:40 411 查看
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) {
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: