Search code examples
javaspring-bootauthenticationsoapwsdl

springboot client for secure soap


I'm trying to access a secure SOAP service from a springboot client and I have this error

StartTransaction Started... equifax | Start transaction ... equifax | Service initialise equifax | 2018-09-20 07:50:38.512 INFO 1 --- [nio-7070-exec-1] o.a.c.w.s.f.ReflectionServiceFactoryBean : Creating Service {http://eid.equifax.com/soap/schema/canada/v3/wsdl}canadav3 from WSDL: https://eid.equifax.ca/uru/soap/ut/canadav3?wsdl equifax | ServicePort initiee equifax | 2018-09-20 07:50:39.558 INFO 1 --- [nio-7070-exec-1] o.a.c.w.s.f.ReflectionServiceFactoryBean : Creating Service {http://eid.equifax.com/soap/schema/canada/v3/wsdl}canadav3 from WSDL: https://eid.equifax.ca/uru/soap/ut/canadav3?wsdl equifax | 2018-09-20 07:50:39.614 INFO 1 --- [nio-7070-exec-1] o.a.c.w.s.f.ReflectionServiceFactoryBean : Creating Service {http://eid.equifax.com/soap/schema/canada/v3/wsdl}canadav3 from WSDL: https://eid.equifax.ca/uru/soap/ut/canadav3?wsdl equifax | org.apache.cxf.binding.soap.SoapFault: An error was discovered processing the header equifax | An error was discovered processing the header

My code:

@ResponseBody
public ResponseEntity<Object> startTransaction(@RequestBody Identity identity) {
    System.out.println("StartTransaction Started...");
    InitialRequest initialRequest = new InitialRequest();
    ProcessingOptions value = new ProcessingOptions();
    value.setLanguage("French");

    initialRequest.setIdentity(identity);
    initialRequest.setProcessingOptions(value);
    InitialResponse iR = new InitialResponse();
    try {
        System.out.println("Start transaction ...");
        Canadav3 canada = new Canadav3();
        System.out.println("Service initialise");
        CanadaPortTypeV3 c = canada.getCanadaHttpPortV3();
        System.out.println("ServicePort initiee");

        URL wsdlURL = new URL("https://eid.equifax.ca/uru/soap/ut/canadav3?wsdl");
        QName qname = new QName("http://eid.equifax.com/soap/schema/canada/v3/wsdl", "Canadav3");
        Service service =Service.create(wsdlURL, qname);
        c = (CanadaPortTypeV3)service.getPort(CanadaPortTypeV3.class);

        BindingProvider bp = (BindingProvider)c;
        bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "/user");
        bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");

        iR = c.startTransaction(initialRequest);
        System.out.println("Finish");
        return ResponseEntity.status(HttpStatus.OK).body(iR);
    }catch (CredentialsErrorFault c) {
        System.err.println("Finish");
        System.err.println("CredentialsErrorFault "+c.getLocalizedMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Alert(c.getMessage()));
    }
    catch(ValidationErrorFault e) {
        System.err.println("Finish");
        System.err.println("ValidationErrorFault "+e.getLocalizedMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Alert(e.getMessage()));
    }
    catch(Exception e) {
        System.out.println(e.getCause());
        System.err.println(e.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Alert("Error unknows"));
    }
}

thank you in advance


Solution

  • I finally have the solution to my problem

    Create a SOAP handler to inject the client authentication information into the SOAP header block for each outgoing SOAP message.

    import java.io.ByteArrayOutputStream;
    import java.util.Set;
    import java.util.logging.Logger;
    
    import javax.xml.namespace.QName;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {
        private static Logger logger = Logger.getLogger(SOAPLoggingHandler.class.getName());
    
        public boolean handleMessage(SOAPMessageContext context) {
                    Boolean outGoingMsg = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
                     SOAPMessage soapMsg = context.getMessage();
    
    
     if(soapMsg != null && soapMsg.getSOAPPart() != null) {
    
            SOAPEnvelope soapEnv;
    
    try {
        soapEnv = soapMsg.getSOAPPart().getEnvelope();
        SOAPHeader soapHeader = soapEnv.getHeader();
        if (soapHeader == null) {
            soapHeader = soapEnv.addHeader();
        }
    
    addAuthentication(soapHeader);
     } catch (SOAPException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
                   }                    
      }
    
    if (outGoingMsg)
          System.out.println("########outgoing soap message######");
      else
          System.out.println("########incoming soap message############");
    
          logSoapMessage(context);     
    
      return true;      
    }
    
    public boolean handleFault(SOAPMessageContext context) {
    
        System.out.println("########Fault soap message######");
         logSoapMessage(context);
    
    return true;      
    }
    
    public void close(MessageContext context) {
    
    }
    
    public void logSoapMessage(SOAPMessageContext context) {
    
     try {
         SOAPMessage msg = context.getMessage();
    
         ByteArrayOutputStream bas = new ByteArrayOutputStream();
         msg.writeTo(bas);
         System.out.println(bas);
     }
     catch (Exception e) {
        System.out.println("Error while writing SOAP message to debug log " + e);
     }
    }
    
    public Set<QName> getHeaders() {
     return null;  
    }
    private void addAuthentication(SOAPHeader header) {
     try {
                           SOAPElement security =header.addChildElement("Security", "wsse", "http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                           SOAPElement usernameToken =
                security.addChildElement("UsernameToken", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
        SOAPElement username = usernameToken.addChildElement("Username", "wsse");
        username.addTextNode("/yourusername");
    
    SOAPElement password =
                usernameToken.addChildElement("Password", "wsse");
        password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
        password.addTextNode("yourpassword");
    
    } catch (Exception e) {
        e.printStackTrace();
    }
    
    }
    }
    

    Then I use it when I call the soap service As do here ( Example: SOAPLoggingHandler.java ) => https://www.juniper.net/documentation/en_US/junos-space16.1/topics/task/operational/junos-space-servicenow-tt-web-service-client-setting.html

    Example–SOAPLoggingHandler.java

    import java.io.ByteArrayOutputStream;
    import java.util.Set;
    import java.util.logging.Logger;
    
    import javax.xml.namespace.QName;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPException;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPEnvelope;
    import javax.xml.soap.SOAPMessage;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    
    public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {
              private static Logger logger = Logger.getLogger(SOAPLoggingHandler.class.getName());
    
               public boolean handleMessage(SOAPMessageContext context) {
                           Boolean outGoingMsg = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
                            SOAPMessage soapMsg = context.getMessage();
    
    
            if(soapMsg != null && soapMsg.getSOAPPart() != null) {
    
                SOAPEnvelope soapEnv;
    
    try {
            soapEnv = soapMsg.getSOAPPart().getEnvelope();
            SOAPHeader soapHeader = soapEnv.getHeader();
            if (soapHeader == null) {
                    soapHeader = soapEnv.addHeader();
                }
    
    addAuthentication(soapHeader);
            } catch (SOAPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
                          }                 
             }
    
    if (outGoingMsg)
                 System.out.println("########outgoing soap message######");
             else
                 System.out.println("########incoming soap message############");
    
                 logSoapMessage(context);     
    
             return true;      
        }
    
        public boolean handleFault(SOAPMessageContext context) {
    
            System.out.println("########Fault soap message######");
                logSoapMessage(context);
    
    return true;      
        }
    
        public void close(MessageContext context) {
    
        }
    
        public void logSoapMessage(SOAPMessageContext context) {
    
            try {
                SOAPMessage msg = context.getMessage();
    
                ByteArrayOutputStream bas = new ByteArrayOutputStream();
                msg.writeTo(bas);
                System.out.println(bas);
            }
            catch (Exception e) {
                System.out.println("Error while writing SOAP message to debug log " + e);
            }
        }
    
    public Set<QName> getHeaders() {
            return null;  
        }
        private void addAuthentication(SOAPHeader header) {
            try {
    
                                  SOAPElement security =
                                                          header.addChildElement("Security", "wsse", "http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
    
                                   SOAPElement usernameToken =
                       security.addChildElement("UsernameToken", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
    
    
               SOAPElement username =
                       usernameToken.addChildElement("Username", "wsse");
               username.addTextNode("***");
    
    SOAPElement password =
                       usernameToken.addChildElement("Password", "wsse");
               password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
               password.addTextNode("***");
    
           } catch (Exception e) {
               e.printStackTrace();
           }
    
        }
    }