3

我想记录一些信息以防出现故障。特别是,我想记录与服务器联系的客户端的 IP 地址和端口,如果安全处于活动状态,则为用户名,如果可能的话,还记录传入的消息。

我在端点的getOutFaultInterceptors 链中添加了一个拦截器,但是在handleMessage 中我不知道可以使用哪些属性。

一些想法?

谢谢

4

3 回答 3

3

在您的端点 xml 定义中,您可以添加以下内容来记录传入消息:

<bean id="logInInterceptor" 
    class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<jaxws:inInterceptors>
    <ref bean="logInInterceptor"/>
</jaxws:inInterceptors>

然后使用总线限制要记录的字符数:

<cxf:bus>
    <cxf:features>
        <cxf:logging limit="102400"/>
    </cxf:features>
<cxf:bus>

您还没有提到您的身份验证方法是什么,所以如果您使用的是 的实现UsernameTokenValidator,您可以在那里记录传入的用户名。

要记录客户端的 IP 地址和端口等详细信息,请扩展LoggingInInterceptor,然后使用以下代码handleMessage()

handleMessage() {
    HttpServletRequest request =
            (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST);
    if (null != request) {              
        String clientAddress = request.getRemoteAddr();
        int remotePort = request.getRemotePort();
        // log them
    }
}

也看看这个线程。

于 2012-06-29T16:00:50.467 回答
2

我是这样解决的

public FaultInterceptor() {
    super(Phase.MARSHAL);
}

public void handleMessage(SoapMessage message) throws Fault {
    Fault fault = (Fault) message.getContent(Exception.class);
    Message inMessage = message.getExchange().getInMessage();
    if (inMessage == null) return;

    String xmlMessage = null;
    InputStream is = inMessage.getContent(InputStream.class);
    String rawXml = null;
    if (is != null) {
        rawXml = is.toString();
    }

    String username = null;
    if (rawXml != null && rawXml.length() > 0) {
        try {
            XPath xpath = XPathFactory.newInstance().newXPath();
            XPathExpression xpathExpression;

            xpathExpression = xpath.compile("//*[local-name()=\'Envelope\']/*[local-name()=\'Header\']/*[local-name()=\'Security\']" +
                    "/*[local-name()=\'UsernameToken\']/*[local-name()=\'Username\']");

            InputSource source = new InputSource(new StringReader(rawXml));

            username = xpathExpression.evaluate(source);
        } catch (XPathExpressionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        xmlMessage = XMLUtils.prittyPrinter(is.toString());
    }

    String clientAddress = "<unknown>";
    int clientPort = -1;
    HttpServletRequest request = (HttpServletRequest)inMessage.get(AbstractHTTPDestination.HTTP_REQUEST); 
    if (null != request) {               
        clientAddress = request.getRemoteAddr(); 
        clientPort = request.getRemotePort();
    }

    logger.warn("User: " + username + " [" + clientAddress + ":" + clientPort + "] caused fault: " + fault +
            "\nMessage received: \n" + xmlMessage);



}

我找到了“inMessage”属性,并在其上找到了原始消息(我可以检索用户名)和从中检索主机和端口的“请求”。

谢谢你。

于 2012-07-02T08:42:02.690 回答
0

我认为您应该在处理故障时将请求输入流视为已消耗。

我建议您始终记录传入的消息,并提取某种消息相关 id - 例如用户名。将其保留为 Message 标头。

对于故障记录,使用仅限于查看输入请求的故障拦截器。

将常规 + 故障日志记录与消息相关 ID 结合在一起。

记录完整的soap请求,而不仅仅是有效负载。除了正文之外,Soap 请求可能还有标头。

请参阅此问题以获取常规日志记录,另外添加一个输出故障拦截器,如下所示:

public class SoapFaultLoggingOutInterceptor extends AbstractPhaseInterceptor<Message> {

    private static final String LOCAL_NAME = "MessageID";

    private static final int PROPERTIES_SIZE = 128;

    private String name = "<interceptor name not set>";

    protected Logger logger = null;
    protected Level level;

    public SoapFaultLoggingOutInterceptor() {
        this(LogUtils.getLogger(SoapFaultLoggingOutInterceptor.class), Level.WARNING);
    }

    public SoapFaultLoggingOutInterceptor(Logger logger, Level reformatSuccessLevel) {
        super(Phase.MARSHAL);
        this.logger = logger;
        this.level = reformatSuccessLevel;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void handleMessage(Message message) throws Fault {
        if (!logger.isLoggable(level)) {
            return;
        }

        StringBuilder buffer = new StringBuilder(PROPERTIES_SIZE);

        // perform local logging - to the buffer 
        buffer.append(name);

        logProperties(buffer, message);

        logger.log(level, buffer.toString());
    }


    /**
     * Gets theMessageID header in the list of headers.
     *
     */
    protected String getIdHeader(Message message) {
        return getHeader(message, LOCAL_NAME);
    }

    protected String getHeader(Message message, String name) {
        List<Header> headers = (List<Header>) message.get(Header.HEADER_LIST);

        if(headers != null) {
            for(Header header:headers) {
                if(header.getName().getLocalPart().equalsIgnoreCase(name)) {
                    return header.getObject().toString();
                }
            }
        }
        return null;
    }        

    protected void logProperties(StringBuilder buffer, Message message) {
        final String messageId = getIdHeader(message);
        if(messageId != null) {
            buffer.append(" MessageId=");
            buffer.append(messageId);
        }

        Message inMessage = message.getExchange().getInMessage();

        HttpServletRequest request = (HttpServletRequest)inMessage.get(AbstractHTTPDestination.HTTP_REQUEST); 

        buffer.append(" RemoteAddr=");
        buffer.append(request.getRemoteAddr());
    }

    public Logger getLogger() {
        return logger;
    }

    public String getName() {
        return name;
    }

    public void setLogger(Logger logger) {
        this.logger = logger;
    }


}    

其中 MessageID 是相关性/面包屑 ID。

于 2015-05-19T12:27:41.193 回答