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 (ユーザー名など) を抽出することをお勧めします。メッセージヘッダーとして保持します。

障害ログには、入力要求の確認に限定された障害インターセプターを使用します。

通常の + 障害ログをメッセージ相関 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 に答える