我想在出現故障時記錄一些信息。 特別是我想記錄與服務器聯繫的客戶端的IP地址和端口,用戶名(如果安全處於活動狀態,並且如果可能的話還有傳入消息)。CXF故障攔截器:記錄有用信息
我在端點的getOutFaultInterceptors鏈中添加了一個攔截器,但在handleMessage中我不知道可以使用哪些屬性。
有些想法?
謝謝
我想在出現故障時記錄一些信息。 特別是我想記錄與服務器聯繫的客戶端的IP地址和端口,用戶名(如果安全處於活動狀態,並且如果可能的話還有傳入消息)。CXF故障攔截器:記錄有用信息
我在端點的getOutFaultInterceptors鏈中添加了一個攔截器,但在handleMessage中我不知道可以使用哪些屬性。
有些想法?
謝謝
我解決這樣
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」屬性並在其上我發現原始消息(我可以檢索用戶名)和從其中我檢索到的主機的「請求」和端口。
謝謝。
在您的端點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
}
}
也看看this線程。
我想你應該查看處理故障時消耗的請求輸入流。
我建議你總是記錄傳入的消息,並提取某種消息關聯ID - 例如用戶名。將其保留爲消息標題。
對於故障記錄,使用故障攔截器,該故障攔截器僅限於查看輸入請求。
將常規+錯誤日誌與消息關聯ID綁定在一起。
記錄完整的肥皂請求,而不僅僅是有效負載。肥皂請求除了正文之外可能還有標題。
定期記錄參見this question,除了添加輸出故障攔截器像這樣:
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。
但是..那麼只有在故障攔截器中記錄這些信息呢? – Francesco