All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.difi.sdp.client2.internal.Wss4jClientSecurityExceptionMapper Maven / Gradle / Ivy

There is a newer version: 7.0.0-RC2
Show newest version
package no.difi.sdp.client2.internal;

import no.difi.sdp.client2.domain.Noekkelpar;
import no.difi.sdp.client2.domain.exceptions.NoekkelException;
import no.difi.sdp.client2.domain.exceptions.SendException;
import no.difi.sdp.client2.domain.exceptions.SikkerDigitalPostException;
import no.difi.sdp.client2.domain.exceptions.UgyldigTidsstempelException;
import no.digipost.api.exceptions.MessageSenderEbmsErrorException;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointExceptionResolver;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityValidationException;

import static no.difi.sdp.client2.domain.exceptions.SendException.AntattSkyldig.*;

/**
 * Even if this class implements the {@see org.springframework.ws.server.EndpointExceptionResolver}, this implementation is injected into our {@see no.digipost.api.interceptors.WsSecurityInterceptor},
 * which is a client interceptor in the context of this library. An {@see org.springframework.ws.server.EndpointExceptionResolver} is supposed to be used by the message dispatcher on the server side.
 * This is why this resolver is used like an exception mapper instead of an exception resolver, and is just a way of dealing with a broken framework. When looking at how exceptions are handled by other
 * client interceptors, for instance {@see org.springframework.ws.client.support.interceptor.PayloadValidatingInterceptor} it is clear that the exceptions are supposed to be thrown in client interceptors
 * in order to handle control flow.
 */
class Wss4jClientSecurityExceptionMapper implements EndpointExceptionResolver {

    /**
     * Maps undlerlying security exceptions into proper, human readable exceptions.
     *
     * @param messageContext
     * @param o
     * @param e
     * @return Will always throw exceptions, so there will never be a return value of true/false. This is contradictory to the interface documentation of {@see EndpointExceptionResolver}
     */
    @Override
    public boolean resolveException(MessageContext messageContext, Object o, Exception e) {
        if (e.getMessage() != null) {
            boolean isPossiblyIncorrectLocalTimeException =
                    (e instanceof Wss4jSecurityValidationException || e instanceof MessageSenderEbmsErrorException)
                            && e.getMessage().contains("Invalid timestamp: The message timestamp is out of range");
            if (isPossiblyIncorrectLocalTimeException) {
                throw new UgyldigTidsstempelException("Ugyldig timestamp i sendt melding. Dette kan skyldes at maskinen som klienten kjører på ikke har stilt klokken korrekt.", e);
            }

            boolean isCouldNotFindTrustedCertificatesException = (e instanceof Wss4jSecurityValidationException && e.getMessage().contains("No trusted certs found"));
            if (isCouldNotFindTrustedCertificatesException) {
                throw new NoekkelException("Klarte ikke å verifisere signatur på responsen. Dette kan skyldes at det tiltrodde rotsertifikatet for Meldingsformidler mangler i keystore eller trust store. " +
                        "Bruk overload for " + Noekkelpar.class.getSimpleName() + " som bruker klientens innebygde sertifikater for trust store eller legg inn mellomliggende sertifikat og rotsertifikat " +
                        "til Buypass og Commfides i trust store.");
            }
        }

        throw new SendException("Under mapping av exception skjedde en feil som ikke kunne håndteres.", UKJENT, e);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy