Search code examples
javaws-securityjava-metro-framework

Programmatically read encrypted error messages from webservice using metro 2.3


Using METRO 2.3 in Netbeans with WS-Security I try to read error messages of an encrypted webservice.

The communication works fine until my payload contains errors. Then the server sends an encrypted error message with the information what went wrong. My client tries to decrypt it and understands that the message got another structure than expected and throws an XMLSignatureException:

javax.xml.crypto.dsig.XMLSignatureException: 
WSS1717: Error occurred while doing digest verification of body/payload

The error message that was send by the server is hidden.

The exception is thrown here in line 146:

http://grepcode.com/file/repo1.maven.org/maven2/org.glassfish.metro/webservices-rt/2.3/com/sun/xml/ws/security/opt/impl/incoming/processor/StreamingPayLoadDigester.java?av=f#146

If I enable the finest logging level, I can read the information that is logged on line 141.

Is ist possible to read the canonicalizedData of the xml stream when I catch the exception?


Solution

  • Since It seems that there is no easy way to do this, I wrote a workaround.

    If I enable Logging on the finest level, too many details are reported. So I wrote my own Log Message Filter.

    Logger wsitlogger = Logger.getLogger("com.sun.xml.wss.logging.impl.opt.signature");
    wsitlogger.setLevel(Level.FINEST);
    TextAndLevelFilter logFilter= new TextAndLevelFilter(Level.INFO);
    logFilter.addPrefix("WSS1764");
    wsitlogger.setFilter(logFilter);
    

    and my TextLevelFilter.java:

    public class TextAndLevelFilter implements Filter {
        private static final int offValue = Level.OFF.intValue();
        private final int levelValue;
    
        private final Collection<String> prefixes = new LinkedList<>();
    
        public TextAndLevelFilter(Level level) {
            this.levelValue = level.intValue();
        }
    
        public void addPrefix(String prefix) {
            prefixes.add(prefix);
        }
    
        @Override
        public boolean isLoggable(LogRecord record) {
            final String message = record.getMessage();
            for (String prefix : prefixes) {
                if (message.startsWith(prefix)) {
                    return true;
                }
            }
            return record.getLevel().intValue() >= levelValue && levelValue != offValue;
        }
    }