Search code examples
javaspringcxfjax-wscxf-client

how to add security header in jax-ws request


I'm creating a jax-ws client with apache cxf. I'm struggling with spring cotext configuration. All I need is to add this header to my soap request:

<soapenv:Header>
  <wsse:Security  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">
     <wsse:UsernameToken wsu:Id="usernametoken">
        <wsse:Username>login</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>        
     </wsse:UsernameToken>
  </wsse:Security>

I have three parameters: usernametoken, password, login.

    <jaxws:client id="***" name="***"
              endpointName="***"
              serviceName="***"
              address="***"
              serviceClass="***"
              username="***"
              password="***"
              xmlns:tns="***">
</jaxws:client>

the code above works and sends soap message, but without security header! Could you give me some ideas how to add that header?


Solution

  • Use this configuration

    <jaxws:client   etc...>
          <jaxws:outInterceptors>     
           <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
              <constructor-arg>
                  <map>
                      <entry key="action" value="UsernameToken"/>
                      <entry key="user" value="login"/>
                      <entry key="passwordType" value="PasswordText"/>
                      <entry key="passwordCallbackRef" value-ref="myPasswordCallback"/>
                   </map>
               </constructor-arg>
            </bean>
          </jaxws:outInterceptors>
       </jaxws:client>
    
       <bean id="myPasswordCallback" class="client.ClientPasswordCallback"/>
    

    And this class to manage the password

    public class ClientPasswordCallback implements CallbackHandler {
    
        public void handle(Callback[] callbacks) throws IOException, 
                UnsupportedCallbackException {
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    
            if ("login".equals(pc.getIdentifier())) {
                pc.setPassword("thepassword");
            } // else {...} - can add more users, access DB, etc.
        }
    }
    

    If you prefer Java code, also is possible

    Client client = ClientProxy.getClient(port);
    Endpoint cxfEndpoint = client.getEndpoint();
    Map<String,Object> outProps = new HashMap<String,Object>();
    outProps.put("action", "UsernameToken");
    outProps.put("user", "login");
    outProps.put("passwordType","PasswordText");
    ClientPasswordCallback c = new ClientPasswordCallback();
    outProps.put("passwordCallbackRef",c);
    
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);