SOAP response/request

P

plork

Hello

Can anyone help me with this one

I have a client that creates a SOAP header.

I have some server-side code that creates a string value.

Can someone tell me how I pass back the string value to my client SOAP header.

I'm using Apache AXIS

Many Thanks
 
I

iksrazal

Hello

Can anyone help me with this one

I have a client that creates a SOAP header.

I have some server-side code that creates a string value.

Can someone tell me how I pass back the string value to my client SOAP header.

I'm using Apache AXIS

Many Thanks

To manipulate the headers, you could use Handlers. These are used alot
for security operations like encryption. They can be used on either/or
the client and server. You don't mention your engine, but the sun
Handler Interface is described in the JWSDP tutorial and is also
supported in Axis.

HTH,
iksrazal
http://www.braziloutsource.com/
 
P

plork

Hello

Can anyone help me with this one

I have a client that creates a SOAP header.

I have some server-side code that creates a string value.

Can someone tell me how I pass back the string value to my client SOAP header.

I'm using Apache AXIS

Many Thanks


To manipulate the headers, you could use Handlers. These are used alot
for security operations like encryption. They can be used on either/or
the client and server. You don't mention your engine, but the sun
Handler Interface is described in the JWSDP tutorial and is also
supported in Axis.


Hello,

That's what i want

What's the best way of writing the handlers - i have a
SOAPHandler.jaav and a LoginHandler.java file

I think l i'm missing something - well i must be think cos i'm not
understanding this

Most of the code i'm writing at the moment is server-side, so i
haven't done any of the wsdl/xml etc.. files yet

My client will create a header, it will then go off to my loginhandler
passing parameters username and password, validate them with backend
db table. Then server-side will return a token value - just a string,
and put the token details into a token table on the db. Then i put
the value of the token in the client-side header. What i want to do
next is for every call my client makes i need to pass the token back
to the handlers to make sure it is valid

This is where i am struggling - how to i set the token in the header
to begin with and then how do i pass the token value back to the
handlers to check it's valid , if it isn't i nedd to produce another
token value and send this back to the client header and update it

I'm using eclipse, tomcat , apache axis

Thanks for any help - struggling big time !!
 
I

iksrazal

plork said:
(e-mail address removed) (plork) wrote in message

What's the best way of writing the handlers - i have a
SOAPHandler.jaav and a LoginHandler.java file

I think l i'm missing something - well i must be think cos i'm not
understanding this

Most of the code i'm writing at the moment is server-side, so i
haven't done any of the wsdl/xml etc.. files yet
This is where i am struggling - how to i set the token in the header
to begin with and then how do i pass the token value back to the
handlers to check it's valid , if it isn't i nedd to produce another
token value and send this back to the client header and update it

I'm using eclipse, tomcat , apache axis

Try passing your token as an xml string - much easier. You could also
place a hashmap in the handler as I do in the example I'm giving. IMHO
avoid wsdl like the plague - I speak from experience. The code examples
I give are long but there is a lot to know and its hard stuff at first.


To put a client handler in you path, try:

public String getData (HashMap invokeProps, String in) throws
WebServiceClientException
{
String ret = null;
try
{
//Invoke properties - configurable by user
String LDAPUserName = Utils.getKeyAsString(invokeProps,
"LDAPUserName");
String LDAPUserPassword = Utils.getKeyAsString(invokeProps,
"LDAPUserPassword");
String nameSpaceUri = Utils.getKeyAsString(invokeProps,
"nameSpaceUri");
String endpoint = Utils.getKeyAsString(invokeProps, "endpoint");
String pq = Utils.getKeyAsString(invokeProps, "portQN");
String service = Utils.getKeyAsString(invokeProps, "service");
String timeout = Utils.getKeyAsString(invokeProps, "timeout");

//Get element to encrypt
String elementToEncrypt = Utils.getKeyAsString(handlerConfig,
"elementToEncrypt");

//Add host to HashMap sent to Handler
handlerConfig.put("host", Utils.getKeyAsString(invokeProps,
"host"));
this.handlerConfig.put("elementToEncrypt", elementToEncrypt);
//Initialize all params needed for call
QName svcQName = new QName(endpoint, nameSpaceUri);

QName portQN = new QName(endpoint, pq);

ServiceFactory sf = ServiceFactory.newInstance();
Service svc = sf.createService(svcQName);
/***
Having problems getting the WSDL, but seems to
work without it

Nota - could try changing the web service web.xml
from .jws to *

URL loc = svc.getWSDLDocumentLocation();
*/

//add ClientHandler to chain of events
java.util.List list =
svc.getHandlerRegistry().getHandlerChain(portQN);
list.add(new
javax.xml.rpc.handler.HandlerInfo(ClientHandler.class,this.handlerConfig,null));

Call call = (Call) svc.createCall(portQN);

if (this.debug)
{
Fwlog.debug(this, Fwlog.WI, "Client handler registry size: " +
list.size());
Fwlog.debug(this, Fwlog.WI, "call created");
}

//set timeout - default is 60s
call.setTimeout(new Integer(timeout));

//explicitly name the XML Element to encrypt in parameter mode
call.addParameter(elementToEncrypt, XMLType.XSD_STRING,
String.class, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);

call.setTargetEndpointAddress(endpoint);

call.setOperationName(new QName(nameSpaceUri, service));

call.setUsername(LDAPUserName);
call.setPassword(LDAPUserPassword);

ret = (String) call.invoke( new Object[] { in } );
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new WebServiceClientException("Web Service failed", e);
}

return ret;
}

To get your soap message to xml, you could try invoke in your handlers:


public class SOAPUtility {

/****************************************************************************
* class MyByteArrayOutputStream ajuda em evitando uma copia do
buffer.

****************************************************************************/
private static class MyByteArrayOutputStream extends
ByteArrayOutputStream {
public MyByteArrayOutputStream(){
super();
}
public ByteArrayInputStream getByteArrayInputStream(){
return new ByteArrayInputStream(buf, 0, count);
}
}



/** Uses serialization due to problems in axis
**/
public static Document toDocument(SOAPMessage soapMsg) throws
ParserConfigurationException, SAXException, SOAPException,
IOException {
MyByteArrayOutputStream baos = new MyByteArrayOutputStream();
soapMsg.writeTo(baos);
ByteArrayInputStream bais = baos.getByteArrayInputStream();

DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(bais);
return doc;
}

/** Uses serialization due to problems in axis
**/
public static SOAPMessage toSOAPMessage(Document doc) throws
TransformerConfigurationException, TransformerException,
SOAPException, IOException, XMLHelperException {
Fwlog.debug(SOAPUtility.class, Fwlog.WI, "Before
SOAPPart set/get Content: " + XMLHelper.getXml(doc));
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
MyByteArrayOutputStream baos = new MyByteArrayOutputStream();
transformer.transform(new DOMSource(doc), new StreamResult(baos));
ByteArrayInputStream bais = baos.getByteArrayInputStream();

MessageFactory mf = MessageFactory.newInstance();
SOAPMessage soapMsg = mf.createMessage(new MimeHeaders(), bais);
return soapMsg;
}


}

Call that in you handlers. The client handler is like:


public class ClientHandler implements Handler
{
private static final String securityDomain = "wssDomain";
private String elementToEncrypt = null;
private String host = null;
private boolean debug;
private X509Certificate cert = null;
private SecretKey secretKey = null;
private PrivateKey privateKey = null;
private String jaas_prop = null;

/** Class contructor **/
public ClientHandler()
{
}

/**
Gerencia uma requisição SOAP no Axis.
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return boolean retorno true para sucesso ou false para parar o
processamento
*/
public boolean handleRequest(MessageContext context)
{
try
{
Fwlog.debug(this, Fwlog.WI, "Entered Client handler
handleRequest()...");

//Login user via LDAP
if (!doLDAPLogin(context))
{
throw new LoginException("\n\nClientHandler::handleRequest
failed, could not **LOGIN** \n\n");
}

SOAPMessageContext soapCtx = (SOAPMessageContext)context;
//Get SOAP message to encrypt and sign
SOAPMessage soapMsg = soapCtx.getMessage();
org.w3c.dom.Document doc = SOAPUtility.toDocument(soapMsg);

Fwlog.debug(this, Fwlog.WI, "Client is signing this SOAP
Document: \n\n" + XMLHelper.getXml(doc));

if(!SecurityHelper.sign(doc, cert, privateKey, debug))
{
throw new
IllegalStateException("\n\nClientHandler::handleRequest failed, could
not **SIGN** soap message\n\n");
}

Fwlog.debug(this, Fwlog.WI, "Client is encrypting this SOAP
Document: \n\n" + XMLHelper.getXml(doc));

if (!SecurityHelper.encrypt(doc, elementToEncrypt, secretKey,
debug))
{
throw new
IllegalStateException("\n\nClientHandler::handleRequest failed, could
not **ENCRYPT** soap message\n\n");
}

soapMsg = SOAPUtility.toSOAPMessage(doc);
soapCtx.setMessage(soapMsg);
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new JAXRPCException(e.toString(), e);
}

Fwlog.debug(this, Fwlog.WI, "ClientHandler: ... handleRequest
executed");
return true;
}

/**
Gerencia uma resposta SOAP no Axis.
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return boolean retorno true para sucesso ou false para parar o
processamento.
*/
public boolean handleResponse(MessageContext context)
{
try
{
Fwlog.debug(this, Fwlog.WI, "Entered Client handler
handleResponse()...");
//Login user via LDAP
if (!doLDAPLogin(context))
{
throw new LoginException("\n\nClientHandler::handleResponse
failed, could not **LOGIN** \n\n");
}
SOAPMessageContext soapCtx = (SOAPMessageContext)context;
SOAPMessage soapMsg = soapCtx.getMessage();
org.w3c.dom.Document doc = SOAPUtility.toDocument(soapMsg);

Fwlog.debug(this, Fwlog.WI, "Client is decrypting this SOAP
Document: \n " + XMLHelper.getXml(doc));

if (!SecurityHelper.decrypt(doc, secretKey, debug))
{
throw new
IllegalStateException("\n\nClientHandler::handleResponse failed, could
not **DECRYPT** soap message\n\n");
}

Fwlog.debug(this, Fwlog.WI, "Client is validating this SOAP
Document: \n" + XMLHelper.getXml(doc));

if (!SecurityHelper.verify(doc))
{
throw new
IllegalStateException("\n\nClientHandler::handleResponse failed, could
not **VERIFY** soap message\n\n");
}

soapMsg = SOAPUtility.toSOAPMessage(doc);
if (debug)
{
Fwlog.debug(this, Fwlog.WI, "\n\nClientHandler::handleResponse
returning Xml Signature validated, decrypted and deserialized XML doc
to SOAP service: \n\n" + XMLHelper.getXml(doc));
}

soapCtx.setMessage(soapMsg);
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new JAXRPCException(e.toString(), e);
}

Fwlog.debug(this, Fwlog.WI, "ClientHandler: ... handleResponse
executed");
return true;
}

/**
Gerencia um erro ocorrido com esta requisição SOAP no Axis.
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return boolean retorno true para sucesso ou false para parar o
processamento
*/
public boolean handleFault(MessageContext context)
{
Fwlog.debug(this, Fwlog.WI, "ClientHandler: In handleFault");
return true;
}

/**
Carrega todos os parâmetros de configuração para o funcionamento
do WS-Security.
<p>
@param config Basicamente um HashMap definido
no arquivo deploy.wssd para o web service que permite
receber os variavies do usuário.
*/
public void init(HandlerInfo config)
{
Fwlog.debug(this, Fwlog.WI, "ClientHandler: init ...");
try
{
jaas_prop = System.getProperty("jaas.prop");
if (null == jaas_prop)
{
throw new IllegalStateException("jaas_prop not set, must point
to login config file 'wssDomain.cfg' needed for
java.security.auth.login.config");
}

Map configProps = config.getHandlerConfig();

if (configProps.containsKey("elementToEncrypt"))
{
elementToEncrypt = (String)configProps.get("elementToEncrypt");
}
else
{
throw new IllegalStateException("Handler chain config property
missing: elementToEncrypt");
}

if (configProps.containsKey("host"))
{
host = (String)configProps.get("host");
}
else
{
throw new IllegalStateException("Handler chain config property
missing: host");
}

if (configProps.containsKey("verbose"))
{
String verbose = (String)configProps.get("verbose");
if (verbose.equalsIgnoreCase("on"))
{
debug = true;
}
else if (verbose.equalsIgnoreCase("off"))
{
debug = false;
}
else
{
throw new IllegalStateException("verbose config property not
'on' or 'off': " + verbose);
}
}
else
{
throw new IllegalStateException("Handler chain config property
missing: verbose");
}
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new JAXRPCException(e.toString(), e);
}
}

/**
Esse metodo precisa ser implementado via interface Handler
*/
public void destroy()
{
}

/**
Esse metodo precisa ser implementado via interface Handler
@return QName volta null
*/
public javax.xml.namespace.QName[] getHeaders()
{
return null;
}

/**
Logar o usário
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return true ou false
*/
public boolean doLDAPLogin(javax.xml.rpc.handler.MessageContext
javaxcontext)
{
try
{
org.apache.axis.MessageContext mc =
(org.apache.axis.MessageContext) javaxcontext;
//set jass config parameter on every call to prevent environment
hell

System.getProperties().setProperty("java.security.auth.login.config",
this.jaas_prop);
// login user via JAAS
CallbackHandler callbackHandler = new WSSCallbackHandler(mc,
this.host);
LoginContext lc = new LoginContext(securityDomain,
callbackHandler);
lc.login();
Fwlog.debug(this, Fwlog.WI, "User logged in successfully: " +
mc.getUsername());

// Get instance from singleton
WSSecurityManager wsm = WSSecurityManager.getInstance();
// Get get X509 certificate needed to sign message
this.cert = wsm.getCert(mc.getUsername());
// Get PrivateKey needed to sign X509 Certificate
this.privateKey = wsm.getPrivateKey(mc.getUsername());
// Get SecretKey needed to encrypt/decrypt message
this.secretKey = wsm.getSecretKey(mc.getUsername());
Fwlog.debug(this, Fwlog.WI, "Got cert, pk and sk for user: " +
mc.getUsername());
return true;
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, "ServiceHandler::doLDAPLogin --
Exception: ");
Fwlog.error(this, Fwlog.WI, e);
return false;
}
}
}

Server side hanlder is just the opposite:

/**
Implementa um Axis Handler. Atua como um XML firewall para todos os
pedidos e repostas
para o web service servidor.

@author Robert Lazarski
*/
public class ServiceHandler implements Handler
{
private String host = null;
private boolean debug;
private static final String securityDomain = "wssDomain";
private X509Certificate cert = null;
private PrivateKey privateKey = null;
private SecretKey secretKey = null;
private String jaas_prop = null;

/** Class contructor **/
public ServiceHandler()
{
}

/**
Gerencia uma requisição SOAP no Axis.
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return boolean retorno true para sucesso ou false para parar o
processamento
*/
public boolean handleRequest(MessageContext context)
{
try
{
Fwlog.debug(this, Fwlog.WI, "Entered Service handler
handleRequest()...");

//Login user via LDAP
if (!doLDAPLogin(context))
{
throw new LoginException("\n\nServiceHandler::handleRequest
failed, could not **LOGIN** \n\n");
}

SOAPMessageContext soapCtx = (SOAPMessageContext)context;
SOAPMessage soapMsg = soapCtx.getMessage();
Document doc = SOAPUtility.toDocument(soapMsg);

if (!SecurityHelper.decrypt(doc, secretKey, debug))
{
throw new
IllegalStateException("\n\nServiceHandler::handleRequest failed, could
not **DECRYPT** soap message\n\n");
}
if (!SecurityHelper.verify(doc))
{
throw new
IllegalStateException("\n\nServiceHandler::handleRequest failed, could
not **VERIFY** soap message\n\n");
}

soapMsg = SOAPUtility.toSOAPMessage(doc);
if (debug)
{
Fwlog.debug(this, Fwlog.WI, "\n\nServiceHandler:: handleRequest
**RECIEVED** Xml Signature validated, decrypted and deserialized XML
doc to SOAP service: \n\n" + XMLHelper.getXml(doc));
}

soapCtx.setMessage(soapMsg);
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new JAXRPCException(e.toString(), e);
}

Fwlog.debug(this, Fwlog.WI, "Service handler handleRequest()
completed, returning true");
return true;
}

/**
Gerencia uma resposta SOAP no Axis.
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return boolean retorno true para sucesso ou false para parar o
processamento.
*/
public boolean handleResponse(MessageContext context)
{
try
{
Fwlog.debug(this, Fwlog.WI, "Entered Service handler
handleResponse()...");

SOAPMessageContext soapCtx = (SOAPMessageContext)context;
SOAPMessage soapMsg = soapCtx.getMessage();
Document doc = SOAPUtility.toDocument(soapMsg);

if (!SecurityHelper.sign(doc, cert, privateKey, debug))
{
throw new
IllegalStateException("\n\nServiceHandler::handleResponse failed, could
not **SIGN** soap message\n\n");
}
if (!SecurityHelper.encrypt(doc, getElementToEncrypt(context),
secretKey, debug))
{
throw new
IllegalStateException("\n\nServiceHandler::handleResponse failed, could
not **ENCRYPT** soap message\n\n");
}

soapMsg = SOAPUtility.toSOAPMessage(doc);

if (debug)
{
Fwlog.debug(this, Fwlog.WI, "\n\nServiceHandler::handleResponse
**RETURNING** Xml Signature signed, encrypted and deserialized XML doc
to SOAP service: \n\n" + XMLHelper.getXml(doc));
}

soapCtx.setMessage(soapMsg);
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new JAXRPCException(e.toString(), e);
}

Fwlog.debug(this, Fwlog.WI, "Service handler handleResponse()
completed, returning true");
return true;
}

/**
Gerencia um erro ocorrido com esta requisição SOAP no Axis.
<p>
@param context Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return boolean retorno true para sucesso ou false para parar o
processamento
*/
public boolean handleFault(MessageContext context)
{
Fwlog.error(this, Fwlog.WI, "ServiceHandler::handleFault
recieved");
return true;
}

/**
Carrega todos os parâmetros de configuração para o funcionamento
do WS-Security.
<p>
@param config Basicamente um HashMap definido
no arquivo deploy.wssd para o web service que permite
receber os variavies do usuário.
*/
public void init(HandlerInfo config)
{
Fwlog.debug(this, Fwlog.WI, "ServiceHandler: init ...");
try
{
jaas_prop = System.getProperty("jaas.prop");
if (null == jaas_prop)
{
throw new IllegalStateException("jaas_prop not set, must point
to login config file 'wssDomain.cfg' needed for
java.security.auth.login.config");
}

Map configProps = config.getHandlerConfig();

if (configProps.containsKey("host"))
{
host = (String)configProps.get("host");
}
else
{
throw new IllegalStateException("Handler chain config property
missing: host");
}

if (configProps.containsKey("verbose"))
{
String verbose = (String)configProps.get("verbose");
if (verbose.equalsIgnoreCase("on"))
{
debug = true;
}
else if (verbose.equalsIgnoreCase("off"))
{
debug = false;
}
else
{
throw new IllegalStateException("verbose config property not
'on' or 'off': " + verbose);
}
}
else
{
throw new IllegalStateException("Handler chain config property
missing: verbose");
}
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, e);
throw new JAXRPCException(e.toString(), e);
}

Fwlog.debug(this, Fwlog.WI, "Service handler init() completed");
}

/**
Esse metodo precisa ser implementado via interface Handler
*/
public void destroy()
{
}

/**
Esse metodo precisa ser implementado via interface Handler
@return QName volta null
*/
public javax.xml.namespace.QName[] getHeaders()
{
return null;
}

/**
Logar o usário
@return true ou false
*/
public boolean doLDAPLogin(javax.xml.rpc.handler.MessageContext
javaxcontext)
{
try
{
org.apache.axis.MessageContext mc =
(org.apache.axis.MessageContext) javaxcontext;
//set jass config parameter on every call to prevent environment
hell

System.getProperties().setProperty("java.security.auth.login.config",
this.jaas_prop);
// login user via JAAS
CallbackHandler callbackHandler = new WSSCallbackHandler(mc,
this.host);
LoginContext lc = new LoginContext(securityDomain,
callbackHandler);
lc.login();
Fwlog.debug(this, Fwlog.WI, "User logged in successfully: " +
mc.getUsername());

// Get instance from singleton
WSSecurityManager wsm = WSSecurityManager.getInstance();
// Get get X509 certificate needed to sign message
this.cert = wsm.getCert(mc.getUsername());
Fwlog.debug(this, Fwlog.WI, "Got cert for user: " +
mc.getUsername());
// Get PrivateKey needed to sign X509 Certificate
this.privateKey = wsm.getPrivateKey(mc.getUsername());
// Get SecretKey needed to encrypt/decrypt message
this.secretKey = wsm.getSecretKey(mc.getUsername());
Fwlog.debug(this, Fwlog.WI, "Got pk and sk for user: " +
mc.getUsername());
return true;
}
catch (Exception e)
{
Fwlog.error(this, Fwlog.WI, "ServiceHandler::doLDAPLogin --
Exception: ");
Fwlog.error(this, Fwlog.WI, e);
return false;
}
}

/**
Pega o nome do Element para encryptar

@param javaxcontext Tudo disponível de SOAP message - headers,
envelopes, body etc.
@return nome do Element
*/
private String
getElementToEncrypt(javax.xml.rpc.handler.MessageContext javaxcontext)
throws java.io.IOException
{
org.apache.axis.MessageContext mc =
(org.apache.axis.MessageContext) javaxcontext;
String service = mc.getOperation().getName();
if(null == service || service.length() < 1)
{
throw new IOException("Web Service name must not be null or
blank");
}
StringBuffer sb;

//nome do servico + 'Return'
//<parameter name="elementToEncrypt" value="ns1:hub_indiceReturn"/>

sb = new StringBuffer();
sb.append("ns1:");
sb.append(service);
sb.append("Return");
return sb.toString();
}
}

HTH,
iksrazal
http://www.braziloutsource.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top