They are used when you define your service client or service provider:
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor"> <property name="prettyLogging" value="false" /> </bean> <bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor"> <property name="prettyLogging" value="false" /> </bean> <jaxws:client id="myWSClient" name="xxxxx" serviceClass="xxxxx" address="xxxxx"> <jaxws:outInterceptors> <ref bean="loggingOutInterceptor" /> </jaxws:outInterceptors> <jaxws:inInterceptors> <ref bean="loggingInInterceptor" /> </jaxws:inInterceptors> </jaxws:client>
In this way, you get a Log of the outbound and inbound messages in your application.
The problem is that you are also logging sensitive information, like user passwords, in case they are sent in plain text (often happens). So, I want to transform specific xml tags content (SOAP messages are xml based) in '*'. For example:
Outbound Message --------------------------- ID: 4 Address: https://desarr.local/accesosweb/servizos/entrada Encoding: UTF-8 Http-Method: POST Content-Type: text/xml Headers: {Accept=[*/*], Connection=[Keep-Alive], SOAPAction=["http://tempuri.org/ObtenerAplicaciones"]} Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ObtenerAplicaciones xmlns="http://tempuri.org/"><usuario><Uid>Sisifo</Uid><password>**********</password></usuario></ObtenerAplicaciones></soap:Body></soap:Envelope> --------------------------------------
Both CXF logging interceptors extends from AbstractLoggingInterceptor. In this class there is a protected method called transform. As this javadoc states, it is meant to mask sensitive information:
Transform the string before display. The implementation in this class does nothing. Override this method if you wish to change the contents of the logged message before it is delivered to the output. For example, you can use this to mask out sensitive information.So you only need to extend these interceptors and override this method. You receives the message before it is printed, so you have to extract the sensitive data and to convert then in whatever you want.
I created a class called LoggingTransform, which implements the same signature as the transform method. In the constructor, it receives the list o tags to filter. For example, if you want to mask '<password>myPass</password>' you identify it with 'password'. It does not have xpath query support.
LoggingTransform
import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LoggingTransform { private final List<Pattern> patterns; public LoggingTransform(final List<String> tagsToFilter) { patterns = new ArrayList<Pattern>(); for (final String tagToFilter : tagsToFilter) { patterns.add(buildNewPattern(tagToFilter)); } } private Pattern buildNewPattern(final String tagName) { return Pattern.compile( String.format("<%s>(.+?)</%s>", tagName, tagName), Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); } public String transform(final String originalLogString) { String filtered = originalLogString; for (final Pattern pattern : patterns) { final Matcher matcher = pattern.matcher(originalLogString); while (matcher.find()) { filtered = filter(filtered, matcher.start(1), matcher.end(1)); } } return filtered; } private String filter(final String original, final int posIni, final int posFin) { return original.substring(0, posIni) + repeat("*", posFin - posIni) + original.substring(posFin); } private String repeat(final String str, final int times) { return new String(new char[times]).replace("\0", str); } }
Then you create the two interceptors, wich extends from their respective CXF interceptors, and override the transform method. In this method you have to calle the LoggingTransform´s transform method.
FilteredLoggingInInterceptor
import java.util.List; import org.apache.cxf.interceptor.LoggingInInterceptor; public class FilteredLoggingInInterceptor extends LoggingInInterceptor { private final LoggingTransform loggingTransform; public FilteredLoggingInInterceptor(final List<String> tagsToFilter) { loggingTransform = new LoggingTransform(tagsToFilter); } @Override public String transform(final String originalLogString) { return loggingTransform.transform(originalLogString); } }
FilteredLoggingOutInterceptor
import java.util.List; import org.apache.cxf.interceptor.LoggingOutInterceptor; public class FilteredLoggingOutInterceptor extends LoggingOutInterceptor { private final LoggingTransform loggingTransform; public FilteredLoggingOutInterceptor(final List<String> tagsToFilter) { loggingTransform = new LoggingTransform(tagsToFilter); } @Override public String transform(final String originalLogString) { return loggingTransform.transform(originalLogString); } }
And finally, declare your new interceptors.
<bean id="loggingOutInterceptor" class="es.sisifo.cxf.logging.FilteredLoggingOutInterceptor"> <constructor-arg name="tagsToFilter"> <list> <value>password</value> <value>otherSensitiveTag</value> </list> </constructor-arg> <property name="prettyLogging" value="false" /> </bean> <bean id="loggingInInterceptor" class="es.sisifo.cxf.logging.FilteredLoggingInInterceptor"> <constructor-arg name="tagsToFilter"> <list> <value>password</value> <value>otherSensitiveTag</value> </list> </constructor-arg> <property name="prettyLogging" value="false" /> </bean>
No hay comentarios:
Publicar un comentario