简体   繁体   中英

Disable Jax-WS Apache CXF HTTPConduit Message Logging

I've been stuck on this one the last couple of days to no avail and after a lot of googling and trial and error I'm back at the beginning with no luck.

I'm currently working on a Java Application which connects to a third party via JAX-WS. They provide a WSDL which we run in using the jaxws-maven-plugin to generate the services. Implemented via Spring, HTTPConduit is then used to change the endpoints and provide relevant config (eg keystores) for connecting to various environments (eg SysTest, UAT, Production etc).

The issue is, I haven't set any logging (in fact removing the two interceptors there previously), however the xml message being sent to the third party is appearing in the logs. This is a major issue as we're sending credit card information to the third parties which can no way be logged for obvious reasons. I can change the log4j properties in order to prevent the logging that way, but that's no way a fix.

Here is some code: This is our beans file.

<jaxws:client id="client1"
              xmlns:hsn="http://example.com"
              serviceClass="com.example.Service1"
              address="${service1.url}"
              endpointName="hsn:service1"/>

<jaxws:client id="client2"
              xmlns:hsn="http://example.com"
              serviceClass="com.example.Service2"
              address="${service2.url}"
              endpointName="hsn:service2"/>

<jaxws:client id="client3"
              xmlns:hsn="http://example.com"
              serviceClass="com.example.Service3"
              address="${service3.url}"
              endpointName="hsn:service3"/>

<http:conduit name="https://*/.*">
    <http:tlsClientParameters disableCNCheck="${service.disable-cn-check}">
        <sec:keyManagers keyPassword="${service.keystore.password}">
            <sec:keyStore type="JKS" password="${service.keystore.password}"
                          resource="${service.keystore.name}"/>
        </sec:keyManagers>
        <sec:trustManagers>
            <sec:keyStore type="JKS" password="${service.truststore.password}"
                          resource="${service.truststore.name}"/>
        </sec:trustManagers>
        <sec:cipherSuitesFilter>
            <sec:include>.*_EXPORT_.*</sec:include>
            <sec:include>.*_EXPORT1024_.*</sec:include>
            <sec:include>.*_WITH_DES_.*</sec:include>
            <sec:include>.*_WITH_AES_.*</sec:include>
            <sec:include>.*_WITH_NULL_.*</sec:include>
            <sec:exclude>.*_DH_anon_.*</sec:exclude>
        </sec:cipherSuitesFilter>
    </http:tlsClientParameters>
    <http:client AutoRedirect="true" Connection="Keep-Alive"
                 ConnectionTimeout="${service.max-response-time}"
                 ReceiveTimeout="${service.max-response-time}"/>

</http:conduit>

<http:conduit name="http://*/.*">
    <http:client AutoRedirect="true" Connection="Keep-Alive"
                 ConnectionTimeout="${service.max-response-time}"
                 ReceiveTimeout="${service.max-response-time}"/>
</http:conduit>

As you can see there are no logging interceptors or logging explicitly turned on using:

<cxf:bus>
    <cxf:features>
        <cxf:logging/>
    </cxf:features>
</cxf:bus>

The only other related file I can think of is META-INF/cxf/org.apache.cxf.Logger which contains:

org.apache.cxf.common.logging.Slf4jLogger

Which even without the file present doesn't make any changes.

Just so you can see, here is a sample from the logs as well:

15:05:45.742 DEBUG | org.apache.cxf.phase.PhaseInterceptorChain  - Invoking handleMessage on interceptor org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor@5e62b59d
15:05:45.742 DEBUG | org.apache.cxf.transport.http.Headers  - Accept: */*
15:05:45.743 DEBUG | org.apache.cxf.transport.http.Headers  - Connection: Keep-Alive
15:05:45.743 DEBUG | org.apache.cxf.transport.http.Headers  - SOAPAction: ""
15:05:45.744 DEBUG | org.apache.cxf.transport.http.HTTPConduit  - No Trust Decider for Conduit '{http://example.com}service1.http-conduit'. An afirmative Trust Decision is assumed.
15:05:45.746 DEBUG | org.apache.cxf.transport.http.HTTPConduit  - Sending POST Message with Headers to http://localhost:8080/stubs/Service1 Conduit :{http://example.com}service1.http-conduit

15:05:45.746 DEBUG | org.apache.cxf.transport.http.HTTPConduit  - Conduit "{http://example.com}service1.http-conduit" Transmit cached message to: http://localhost:8080/stubs/Service1: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>********************HERE LIES THE XML MESSAGE*********************</soap:Body></soap:Envelope>
15:05:45.766 DEBUG | org.apache.cxf.endpoint.ClientImpl  - Interceptors contributed by bus: [org.apache.cxf.ws.policy.PolicyInInterceptor@24ec87dc]
15:05:45.767 DEBUG | org.apache.cxf.endpoint.ClientImpl  - Interceptors contributed by client: []
15:05:45.767 DEBUG | org.apache.cxf.endpoint.ClientImpl  - Interceptors contributed by endpoint: [org.apache.cxf.jaxws.interceptors.WrapperClassInInterceptor@52d1f1fb, org.apache.cxf.jaxws.interceptors.HolderInInterceptor@5565c037, org.apache.cxf.jaxws.interceptors.SwAInInterceptor@b2e86ae, org.apache.cxf.frontend.WSDLGetInterceptor@1ca801a2]
15:05:45.768 DEBUG | org.apache.cxf.endpoint.ClientImpl  - Interceptors contributed by binding: [org.apache.cxf.interceptor.AttachmentInInterceptor@1b8c0f3e, org.apache.cxf.interceptor.StaxInInterceptor@83cbd93, org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor@4bc2021e, org.apache.cxf.interceptor.DocLiteralInInterceptor@2e19266d, org.apache.cxf.binding.soap.interceptor.SoapHeaderInterceptor@7529d5bf, org.apache.cxf.binding.soap.interceptor.ReadHeadersInterceptor@d902ab1, org.apache.cxf.binding.soap.interceptor.StartBodyInterceptor@73e2d16b, org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor@3023033d, org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor@4aa9b27b]
15:05:45.768 DEBUG | org.apache.cxf.endpoint.ClientImpl  - Interceptors contributed by databinging: [org.apache.cxf.jaxb.attachment.JAXBAttachmentSchemaValidationHack@331fef77]
15:05:45.769 DEBUG | org.apache.cxf.phase.PhaseInterceptorChain  - Chain org.apache.cxf.phase.PhaseInterceptorChain@273221e was created. Current flow:
  receive [PolicyInInterceptor, AttachmentInInterceptor]
  post-stream [StaxInInterceptor]
  read [WSDLGetInterceptor, ReadHeadersInterceptor, SoapActionInInterceptor, StartBodyInterceptor]
  pre-protocol [MustUnderstandInterceptor]
  post-protocol [CheckFaultInterceptor, JAXBAttachmentSchemaValidationHack]
  unmarshal [DocLiteralInInterceptor, SoapHeaderInterceptor]
  post-logical [WrapperClassInInterceptor]
  pre-invoke [SwAInInterceptor, HolderInInterceptor]

15:05:45.769 DEBUG | org.apache.cxf.phase.PhaseInterceptorChain  - Invoking handleMessage on interceptor org.apache.cxf.ws.policy.PolicyInInterceptor@24ec87dc

Just add logback.xml file in your class path with logger level INFO, it will disable all output from CXF DEBUGS.

Sample File

Filename : logback.xml Location : src/main/resources (In my project its resources, you can place the file accordingly in your project classpath)

File Content:

<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
    <resetJUL>true</resetJUL>
</contextListener>

<!-- To enable JMX Management -->
<jmxConfigurator/>

<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<logger name="com.mycompany.subpackage" level="INFO"/>

<root level="INFO">
    <appender-ref ref="console"/>
</root>

Few months back I had come across similar problem, where I needed to mask few fields of my xml

The CustomLoginInterceptor

import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingMessage;

public class KPLogInInterceptor extends LoggingInInterceptor {

    @Override
    protected String formatLoggingMessage(LoggingMessage loggingMessage) {

        String str = loggingMessage.toString();

        String output = maskPasswords(str);
        //output = maskRestPasswords(output);
        return(output);
    }


    private String maskPasswords(String str) {

        // String str =
                // "<password1>asdasdad</password1><Password3></Password3><Password5/><PassWord6>fdsfsf</PassWord6>";
                final String[] keys = { "password", "authpass", "accountnumber", "authphrase" };
                for (String key : keys) {
                    int beginIndex = 0;
                    int lastIndex = -1;
                    boolean emptyPass = false;
                    boolean multiline = false;
                    if(key.equals("authphrase") || key.equals("authpass"))
                    {
                       //when lines are in multiplelines say <name>authphrase</name><value>vals</value>
                        multiline = true;
                    }
                    while (beginIndex != -1
                            && (beginIndex = StringUtils.indexOfIgnoreCase(str, key,
                                    beginIndex)) > 0) {

                        if(multiline){
                            beginIndex = StringUtils.indexOfIgnoreCase(str, "value", beginIndex);
                        }
                        beginIndex = StringUtils.indexOf(str, ">", beginIndex);
                        if (beginIndex != -1) {
                            char ch = str.charAt(beginIndex - 1);
                            if (ch == '/') {
                                emptyPass = true;
                            }
                            if (!emptyPass) {
                                lastIndex = StringUtils.indexOf(str, "<", beginIndex);
                                if (lastIndex != -1) {
                                    String overlay = "*";
                                    String str2 = StringUtils.substring(str,
                                            beginIndex + 1, lastIndex);
                                    if (str2 != null && str2.length() > 1) {
                                        overlay = StringUtils.rightPad(overlay,
                                                str2.length(), "*");
                                        str = StringUtils.overlay(str, overlay,
                                                beginIndex + 1, lastIndex);
                                    }
                                }
                            }
                            if (emptyPass) {
                                emptyPass = false;
                                lastIndex = beginIndex + 1;
                            } else {
                                if (lastIndex != -1) {
                                    lastIndex = StringUtils
                                            .indexOf(str, ">", lastIndex);
                                }
                            }
                        }
                        beginIndex = lastIndex;
                    }
                }
                return str;

            }
}

And the cxf config xml

<bean id="kpInInterceptor" class="com.kp.swasthik.KPLogInInterceptor"></bean>
<bean id="kpOutInterceptor" class="com.kp.swasthik.KPLogOutInterceptor"></bean>

    <cxf:bus>
        <cxf:inInterceptors>
            <ref bean="kpInInterceptor" />
        </cxf:inInterceptors>
        <cxf:outInterceptors>
            <ref bean="kpOutInterceptor" />
        </cxf:outInterceptors>
        <cxf:outFaultInterceptors>
            <ref bean="kpOutInterceptor" />
        </cxf:outFaultInterceptors>
        <cxf:inFaultInterceptors>
            <ref bean="kpInInterceptor" />
        </cxf:inFaultInterceptors>
    </cxf:bus>

You need to create one more class that extends LogOutInterceptor

EDIT

Create class the sets the loglevel to INFO for

public class KPLogicSupresser {

    public void kpinit(){

        LogManager.getLogger(HTTPConduit.class).setLevel(Level.INFO);


    }


}

And create a bean in CXF configuration file

<bean id="kpLog4Jsupresser" class="com.kp.swasthik.KPLogicSupresser" init-method="kpinit" ></bean>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM