views:

504

answers:

2

I'm using WSS4J to add a Username token in the header of an already formed SOAP request envelope.

Here is what the SOAP request looks like:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://sample03.samples.rampart.apache.org/xsd"&gt;   
   <soapenv:Header/>   
   <soapenv:Body>      
      <xsd:echo>         
         <xsd:param0>hurro kitty</xsd:param0>      
      </xsd:echo>   
   </soapenv:Body></soapenv:Envelope>

This is my code (the String, request, is the request above):

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inStream = new InputSource();
inStream.setCharacterStream(new StringReader(request));
Document document = builder.parse(inStream);

WSSecUsernameToken usernametoken = new WSSecUsernameToken();
usernametoken.setPasswordType(WSConstants.PASSWORD_TEXT);
usernametoken.setUserInfo(username, password);

WSSecHeader secHeader = new WSSecHeader("", false);
secHeader.insertSecurityHeader(document);
usernametoken.build(document, secHeader);

This is my result (notice the header that was inserted is not namespaced correctly, as well as there being two headers):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://sample03.samples.rampart.apache.org/xsd"&gt;   
   <Header>      
      <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"&gt;         
         <wsse:UsernameToken wsu:Id="UsernameToken-2765109" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;            
            <wsse:Username>bob</wsse:Username>            
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"&gt;bobPW&lt;/wsse:Password&gt;         
         </wsse:UsernameToken>      
      </wsse:Security>   
   </Header>   
   <soapenv:Header/>   
   <soapenv:Body>      
      <xsd:echo>         
         <xsd:param0>hurro kitty</xsd:param0>      
      </xsd:echo>   
   </soapenv:Body></soapenv:Envelope>

What am I doing wrong?

+1  A: 

What am I doing wrong?

When you are building the initial XML, you need to make sure that the DocumentBuilderFactory is namespace-aware. WSSecurity is trying to find the soap header by the soap namespace but it isn't available. Adding the following line should fix it:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
...
Kevin
A: 

Hi, I have the same question, flowing is shipped codes(this is init and invoke codes):

RemoteLibraryServiceService ss = new RemoteLibraryServiceService();

    ss.setHandlerResolver(new HandlerResolver() {
        public List<Handler> getHandlerChain(PortInfo info) {
            List<Handler> handlerList = new ArrayList<Handler>();
            Handler handler;
            try {
                handler = new ClientSOAPHandlerBase();
                handlerList.add(handler);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return handlerList;
        }
    });

    RemoteLibraryService port = ss.getRemoteLibraryServicePort();
    port.getPassword("username","ip_address");

And flowing is Client Handler class:

public class WSS4jUserNameTokenHandler implements SOAPHandler<SOAPMessageContext> {

public Set<QName> getHeaders() {
    Set<QName> HEADERS = new HashSet<QName>();
    HEADERS.add(new QName(WSConstants.WSSE_NS, "Security"));
    HEADERS.add(new QName(WSConstants.WSSE11_NS, "Security"));
    HEADERS.add(new QName(WSConstants.ENC_NS, "EncryptedData"));

    return HEADERS;
}

public void close(MessageContext context) {
// TODO Auto-generated method stub

}

public boolean handleFault(SOAPMessageContext context) {
    // TODO Auto-generated method stub
    return false;
}

public boolean handleMessage(SOAPMessageContext context) {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    try {
        // got the message from the context
        SOAPMessage msg = context.getMessage();
        Boolean isOutGoing = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (isOutGoing.booleanValue()) {
            //
            DocumentBuilder builder = factory.newDocumentBuilder();
            InputSource inStream = new InputSource();
            inStream.setCharacterStream(new StringReader(""));
            Document document = builder.parse(inStream);

            WSSecUsernameToken usernametoken = new WSSecUsernameToken();
            usernametoken.setPasswordType(WSConstants.PASSWORD_TEXT);
            usernametoken.setUserInfo("user", "password");

            WSSecHeader secHeader = new WSSecHeader("wsse:Security", false);
            secHeader.insertSecurityHeader(document);
            usernametoken.build(document, secHeader);

            // TODO: I have no idea how to continue completed these codes.
        } else {}
    } catch (Exception ex) {
        ex.printStackTrace();
        throw new RuntimeException(ex.getMessage());
    }
    return true;
}}

Above are the codes, but I have no idea how to completed these codes ? Please help me, thanks.

SimpleMan