You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Ma...@sungard.com on 2008/09/12 20:20:41 UTC

what's the best way to handle messaging?

I am currently involved with a project for which my manager wants to
convert existing  module into Web service.  It is a Reporting tool,  a
servlet can return report either in csv/xml once we specify report name,
parameters etc.

Users will first request the list of all available reports and then will
get the specific report depending on the list. I am quite new to web
services as such. I downloaded CXF and tried couple of small samples but
need to know the best way of doing it. 

 

1)      For List - I am thinking of giving client collection of all
report DAOs  (HashMap - with key as report Id)

2)      For specific report - get the DAO from client with report name
and parameters and return back string buffer.

 

But I would like to know normally what's the practice and how I should
handle the messaging between client and server ? Instead of DAOs shall I
use XML ? From performance point of view is there anything I should be
aware of?  

 

Thanks,

Manisha

 

 

 


RE: what's the best way to handle messaging?

Posted by Ma...@sungard.com.
1) I thought over it and realized that if I need to support different
clients then I can't return back Java objects but it should be in XML. 
2) Also management wants to have security in place, so login id/
password will be required, I tried one small tutorial on web
(http://www.lumidant.com/blog/apache-cxf-tutorial-ws-security-with-sprin
g/) for this, which works fine. But my question is if I have to provide
2-3 services, so whether every time client request a service, they will
need to provide login id/password? Or is there any mechanism of storing
the session, same like servlet?

Thanks
Manisha





-----Original Message-----
From: Manisha.Sathe@sungard.com [mailto:Manisha.Sathe@sungard.com] 
Sent: Friday, September 12, 2008 1:21 PM
To: users@cxf.apache.org
Subject: what's the best way to handle messaging?

I am currently involved with a project for which my manager wants to
convert existing  module into Web service.  It is a Reporting tool,  a
servlet can return report either in csv/xml once we specify report name,
parameters etc.

Users will first request the list of all available reports and then will
get the specific report depending on the list. I am quite new to web
services as such. I downloaded CXF and tried couple of small samples but
need to know the best way of doing it. 

 

1)      For List - I am thinking of giving client collection of all
report DAOs  (HashMap - with key as report Id)

2)      For specific report - get the DAO from client with report name
and parameters and return back string buffer.

 

But I would like to know normally what's the practice and how I should
handle the messaging between client and server ? Instead of DAOs shall I
use XML ? From performance point of view is there anything I should be
aware of?  

 

Thanks,

Manisha

 

 

 



Encryption with UserNameToken

Posted by Steve Shaw <st...@intelliware.ca>.
A couple of weeks back, I posted for (and received) assistance in
signing a document with the UsernameToken. I've recently worked out a
method to do a related operation: encrypting (and decrypting) a message
with that same security reference. Unfortunately, it wasn't as
straightforward.

I'm posting my results to the list partly as a record for anyone trying
to do this in the future and partly in the hopes that someone may
eventually try to roll this stuff into the main code base. I'm not
submitting a patch myself because I'm pretty sure I've broken
non-UsernameToken based encryption and because of my unfamiliarity with
the code base.

This will be quite a long message, so unless you've got an unhealthy
fascination with this sort of encryption it may be a good time to go to
the next message.

Part 1: Encryption

Here's the client-side code I used to encrypt my message. Things like
the document and usernameToken have already been defined - see my
earlier postings.

Reference reference = new Reference(document);
reference.setURI("#" + ut.getId());
reference.setValueType("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken");

SecurityTokenReference securityTokenReference = new SecurityTokenReference(document);
securityTokenReference.setReference(reference);

WSSecurityUtil.setNamespace(securityTokenReference.getElement(), WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);

WSSecEncrypt secEncrypt = new WSSecEncrypt();
secEncrypt.setKeyIdentifierType(WSConstants.EMBED_SECURITY_TOKEN_REF);
secEncrypt.setSecurityTokenReference(securityTokenReference);
secEncrypt.setKey(secretKey);
secEncrypt.setSymmetricEncAlgorithm(WSConstants.AES_128);
secEncrypt.setDocument(document);

// this specifies that the encryptMe element should be encrypted, but 
// it could be any combination of elements that gets encrypted
Vector<WSEncryptionPart> encryptionParts = new Vector<WSEncryptionPart>();
String name = "encryptMe";
String namespace = null;
String encMod = "Content";
WSEncryptionPart encryptionPart = new WSEncryptionPart(name, namespace, encMod);
encryptionParts.add(encryptionPart);
secEncrypt.setParts(encryptionParts);
        
secEncrypt.build(document, null, secHeader);

This generates a SOAP message that has been encrypted. It looks something like this (I removed the digital signature fields to make things a little more readable):

<SOAP-ENV:Envelope 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#" >
  <SOAP-ENV:Header>
    <wsse:Security SOAP-ENV:mustUnderstand="1">
      <wsse:UsernameToken wsu:Id="UsernameToken-14721926">
        <wsse:Username>pierre</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">7qSMV2ole4ftWtvaxFMBYX5/YLc=</wsse:Password>
        <wsse:Nonce>jaXk03JWGVBsxJ1TKv0z7Q==</wsse:Nonce>
        <wsu:Created>2008-08-27T21:42:43.018Z</wsu:Created>
      </wsse:UsernameToken>
      <xenc:ReferenceList>
        <xenc:DataReference URI="#EncDataId-1281123"/>
      </xenc:ReferenceList>
    </wsse:Security>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-20000831">
      <helloWorld>
        <stuff>The following bit is encrypted</stuff>
        <encryptMe>
          <xenc:EncryptedData Id="EncDataId-1281123" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
              <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                <wsse:Reference URI="#UsernameToken-14721926" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
              </wsse:SecurityTokenReference>
            </ds:KeyInfo>
            <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
              <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">5lEPD1JcaArVNk9imTSsHLW7n8lTY8F1HGmdkU2gZSNtosRtdA9E3umEjXp4xyeJ</xenc:CipherValue>
            </xenc:CipherData>
          </xenc:EncryptedData>
        </encryptMe>
      </helloWorld>
    </SOAP-ENV:Body>
  </SOAP-ENV:Envelope>

As hoped, only the contents of the <encryptMe> element were encrypted.

Part 2: Decryption

When I attempted to decrypt this message with the standard CXF action, 
I ran into two problems. The first is that the "Encrypt" action always 
forces a lookup of the crypto properties which I didn't have specified 
since it wasn't needed. The second was that WSS4J's ReferenceListProcessor 
was not set up to handle security references of UsernameToken.

I solved both these problems by creating custom versions of the 
WSS4JInInterceptor and ReferenceListProcessor. Subclassing would have 
been preferrable, but the classes were a little resistant to easy 
subclassing due to method size and visibility issues.

Here are my changes to WSS4JInInterceptor:

public WSS4JInInterceptor() {
        super();

        setPhase(Phase.PRE_PROTOCOL);
        getAfter().add(SAAJInInterceptor.class.getName());
        
        // use our custom ReferenceListProcessor
        // this is a little sloppy, see note below
        secEngine.getWssConfig().setProcessor(
                WSSecurityEngine.REFERENCE_LIST, 
                ca.intelliware.common.webservice.ReferenceListProcessor.class.getName());
    }

[...]

    public void handleMessage(SoapMessage msg) throws Fault {
        [...]
            // SS: we remove "Encrypt" from the actions before we pass it into decodeAction.
            // The trick here is that if doAction includes the encrypt bit value, lower-level code
            // automatically tries to look up our crypto information and throws an exception. So
            // we use two sets of values here: doAction has the Encrypt action removed, while actions
            // still has it since that is the one that is compared to the wsResult vector later on.

            String noEncryptAction = StringUtils.remove(action, "Encrypt");
            int doAction = WSSecurityUtil.decodeAction(noEncryptAction, new Vector());
            WSSecurityUtil.decodeAction(action, actions);

[...]

Note that the above code is actually pretty sloppy. secEngine 
is basically a static field that I'm modifying for my purposes. 
However, since I know I'm the only one using it I can do so without 
feeling too bad about it.

There's is an alternate approach to changing up the processors that 
get mapped to different actions: WSS4JInInterceptor has a second constructor 
that takes in a Map of processors to override the defaults. But since I had 
to modify WSS4JInInterceptor anyway to avoid the crypto lookup, I thought 
I'd just put the other reference in the constructor.

And here are the changes I made to ReferenceListProcessor:

private SecretKey getKeyFromSecurityTokenReference(Element secRefToken, String algorithm,
            Crypto crypto, CallbackHandler cb) throws WSSecurityException {
              
                [...]

                    if     (p == null
                        || (!(p instanceof EncryptedKeyProcessor)
                        && !(p instanceof DerivedKeyTokenProcessor) 
                        && !(p instanceof SAMLTokenProcessor)
                        // SS support this type of processor now too
                        && !(p instanceof UsernameTokenProcessor))) {
                
                [...]

                    if(p instanceof EncryptedKeyProcessor) {
                       [...]
                    } else if(p instanceof DerivedKeyTokenProcessor) {
                       [...]
                    } else if(p instanceof SAMLTokenProcessor) {
                       [...]
                    } else if(p instanceof UsernameTokenProcessor) {
                        // SS added UsernameToken handling
                        UsernameTokenProcessor utp = (UsernameTokenProcessor) p;
                        decryptedData = utp.getUt().getSecretKey();
                    }
[...]

With these changes, I was able to encrypt and decrypt messages using the 
UsernameToken security reference. However, in doing so I removed the ability
of the service to properly handle any other sort of encryption. It's more of 
a hack than anything else, but it works for my implementation. Hopefully 
someone will find it of use in the future.

I'm also open to the possibility that there's an easier way to do this, and 
would appreciate any feedback if that is the case.

-Steve