I am currently trying to get the SOAP code to work.
I have downloaded the ZimbraUserService.wsdl and all the related xsd files.
From there i have automatically generated the java code using the apache-cxf-3.3.1 wsdl2java.
After stumbling a bit i wrote a custom AuthRequest to make sure that everything is working correcty
Code: Select all
package com.somewhere.swing.calendar;
import java.net.URL;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
public class soap {
private static String zimbra_user = "user";
private static String zimbra_password = "passsssword;
public static void main(String args[]) {
connectWithRawSoap();
}
private static void connectWithRawSoap() {
String soapEndpointUrl = "http://my-urlservice/soap";
String soapAction = "http://my-url:443/service/soap/AuthRequest";
callSoapWebService(soapEndpointUrl, soapAction);
}
private static void callSoapWebService(String soapEndpointUrl, String soapAction) {
try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
URL url = new URL(soapEndpointUrl);
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), url);
// Print the SOAP Response
System.out.println("Response SOAP Message:");
soapResponse.writeTo(System.out);
System.out.println();
soapConnection.close();
} catch (Exception e) {
System.err.println(
"\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n");
e.printStackTrace();
}
}
private static SOAPMessage createSOAPRequest(String soapAction) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
createSoapEnvelope(soapMessage);
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", soapAction);
soapMessage.saveChanges();
/* Print the request message, just for debugging purposes */
System.out.println("Request SOAP Message:");
soapMessage.writeTo(System.out);
System.out.println("\n");
return soapMessage;
}
private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException {
SOAPPart soapPart = soapMessage.getSOAPPart();
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
Name context = envelope.createName("context", null, "urn:zimbra");
Name xml = envelope.createName("format", "type", "xml");
//context.
Name authRequest = envelope.createName("AuthRequest", null, "urn:zimbraAccount");
Name account = envelope.createName("account");
Name password = envelope.createName("password");
// SOAP Body
SOAPHeader header = envelope.getHeader();
// header.addChildElement(context).addChildElement(xml);
SOAPBody soapBody = envelope.getBody();
SOAPBodyElement auth_body = soapBody.addBodyElement(authRequest);
auth_body.addChildElement(account).addAttribute(envelope.createName("by"), "name").addTextNode(zimbra_user);
auth_body.addChildElement(password).addTextNode(zimbra_password);
}
}
Then i have started working on the wsdl code in order to get that to work.
After a few issues i.e Fixing the PKIX path in order to register the cacert, finding the correct code to send the SOAP command.
I have managed to come up with the following code correctly sends an authentication command and receives the AuthResp
Code: Select all
package com.something.calendar;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import com.zimbra.wsdl.zimbraservice_wsdl.ZcsPortType;
import com.zimbra.wsdl.zimbraservice_wsdl.ZcsService;
import zimbra.AccountBy;
import zimbra.AccountSelector;
import zimbra.AuthTokenControl;
import zimbra.HeaderContext;
import zimbraaccount.AuthRequest;
import zimbraaccount.AuthResponse;
import zimbraaccount.AuthToken;
import zimbraaccount.GetAccountInfoRequest;
import zimbraaccount.GetAccountInfoResponse;
import zimbraaccount.ObjectFactory;
public class SoapTest {
private static String zimbra_user = "user;
private static String zimbra_password = "pass";
static class HeaderHandlerResolver implements HandlerResolver {
@Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
HandlerHeader hh = new HandlerHeader();
handlerChain.add(hh);
return handlerChain;
}
}
static class HandlerHeader implements SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
return Collections.emptySet();
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
try {
System.out.println("\nOutbound message:");
System.out.println("******************");
context.getMessage().writeTo(System.out);
System.out.println("\n******************");
} catch (SOAPException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
System.out.println("\nInbound message:");
SOAPMessage message = context.getMessage();
System.out.println("\n******************");
message.writeTo(System.out);
System.out.println("\n******************");
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
try {
SOAPMessage message = context.getMessage();
ByteArrayOutputStream out = new ByteArrayOutputStream();
message.writeTo(out);
String strMsg = new String(out.toByteArray());
System.err.println("FAULT:");
System.err.println(strMsg);
} catch (SOAPException | IOException ex) {
ex.printStackTrace();
}
return true;
}
@Override
public void close(MessageContext context) {
}
}
public static void main(String args[]) {
connectAndAuthenticate();
}
private static void connectAndAuthenticate() {
ObjectFactory zimbraAccountFactory = new ObjectFactory();
AuthRequest authRequest = zimbraAccountFactory.createAuthRequest();
AccountSelector accountSelector = new AccountSelector();
accountSelector.setBy(AccountBy.NAME);
accountSelector.setValue(zimbra_user);
authRequest.setAccount(accountSelector);
authRequest.setPassword(zimbra_password);
ZcsService service = new ZcsService();
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
service.setHandlerResolver(handlerResolver);
ZcsPortType port = service.getZcsServicePort();
AuthResponse response = port.authRequest(authRequest);
JAXBElement<AuthResponse> response2 = zimbraAccountFactory.createAuthResponse(response);
AuthToken token = zimbraAccountFactory.createAuthToken();
String resp = response2.getValue().getAuthToken();
long lifeTime = response2.getValue().getLifetime();
token.setValue(resp);
token.setLifetime(lifeTime);
authRequest.setAuthToken(token);
zimbra.ObjectFactory zimbraFactory = new zimbra.ObjectFactory();
HeaderContext c = zimbraFactory.createHeaderContext();
c.setAuthToken(resp);
AuthTokenControl tokenControl = zimbraFactory.createAuthTokenControl();
tokenControl.setVoidOnExpired(true);
c.setAuthTokenControl(tokenControl);
GetAccountInfoRequest infoRequest = zimbraAccountFactory.createGetAccountInfoRequest();
infoRequest.setAccount(accountSelector);
GetAccountInfoResponse getAccountInfoRequest = port.getAccountInfoRequest(infoRequest);
zimbraAccountFactory.createGetAccountInfoResponse();
}
}
I have been trying for hours how to send the AuthRespond on to the next Request in order to get the response but what ever i have tried it did not work.
I cant seem to add the authtoken in my commands.
Exception in thread "main" com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: no valid authtoken present Please see the server log to find more detail regarding exact cause of the failure.
Does anyone have any ideas how i can proceed from here and add the AuthResponse into the next commands ?
I have tried to use the following code
viewtopic.php?t=732
But unfortunately the code there is old, and not entirely clear what needs to be done.