Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: make text more Docbook PDF friendly.

...

Code Block
java
java
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.EndpointImpl;

EndpointImpl jaxWsEndpoint = (EndpointImpl) Endpoint.publish("http://host/service", 
    myServiceImpl);
Endpoint cxfEndpoint = jaxWsEndpoint.getServer().getEndpoint();

...

On the client side, you can obtain a reference to the CXF endpoint using the ClientProxy helper:

Code Block
java
java
import org.apache.cxf.frontend.ClientProxy;
...

GreeterService gs = new GreeterService();
Greeter greeter = gs.getGreeterPort();
...
org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(greeter);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

...

Code Block
java
java
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
...

Map<String,Object> inProps= new HashMap<String,Object>();
... // how to configure the properties is outlined below;

WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
cxfEndpoint.getInInterceptors().add(wssIn);
cxfEndpoint.getInInterceptors().add(new SAAJInInterceptor()); // 2.0.x only; not needed in 2.1+

Map<String,Object> outProps = new HashMap<String,Object>();
... // how to configure the properties is outlined below;

WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
cxfEndpoint.getOutInterceptors().add(new SAAJOutInterceptor()); // 2.0.x only; not needed in 2.1+

Spring XML Configuration

If you're using Spring to build endpoints (e.g., web services running on a servlet container such as Tomcat), you can easily accomplish the above using your bean definitions instead.

...

Code Block
xml
xml
<beans
  ...
  xmlns:util="http://www.springframework.org/schema/util"
  ...
  xsi:schemaLocation="
        ...
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util.xsd">

  ...

  <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
    <constructor-arg>
      <map>
        <entry value="UsernameToken">
          <key>
            <util:constant 
                static-field="org.apache.ws.security.handler.WSHandlerConstants.ACTION"/>
          </key>
        </entry>
        ...
      </map>
    </constructor-arg>
  </bean>

  ...  

...

Code Block
java
java
import org.apache.cxf.ws.security.wss4j.CryptoCoverageChecker;
import org.apache.cxf.ws.security.wss4j.CryptoCoverageChecker.XPathExpression;
import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageScope;
import org.apache.cxf.ws.security.wss4j.CryptoCoverageUtil.CoverageType;

Map<String, String> prefixes = new HashMap<String, String>();
        prefixes.put("ser", "http://www.sdj.pl");
        prefixes.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");

List<XPathExpression> xpaths = Arrays.asList(
    new XPathExpression("//ser:Header", CoverageType.SIGNED, 
        CoverageScope.ELEMENT),
    new XPathExpression("//soap:Body", CoverageType.ENCRYPTED, 
        CoverageScope.CONTENT));

CryptoCoverageChecker checker = new CryptoCoverageChecker(prefixes, xpaths);

...

Code Block
xml
xml
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
  <constructor-arg>
    <map>
      ...
      <!-- Redefines the action for SAMLTokenSigned 
               to use a custom implementation.  -->
      <entry key="wss4j.action.map">
        <map key-type="java.lang.Integer" value-type="java.lang.Object">
          <entry key="0x10" value-ref="mySamlTokenSignedAction"/>
        </map>
      </entry>      ...
    </map>
  </constructor-arg>
</bean>

...

Code Block
inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
// Password type : plain text
inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
// for hashed password use:
//properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
// Callback used to retrieve password for given user.
inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, 
    ServerPasswordHandler.class.getName());

...

Code Block
java
java
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;

public class ServerPasswordCallback implements CallbackHandler {

    public void handle(Callback[] callbacks) throws IOException, throws IOException, 
        UnsupportedCallbackException {

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        if (pc.getIdentifergetIdentifier().equals("joe")) {
            // set the password on the callback. This will be compared to the
            // password which was sent from the client.
            pc.setPassword("password");
        }
    }

}

...

Code Block
java
java
public class ServerPasswordCallback implements CallbackHandler {

    public void handle(Callback[] callbacks) throws IOException, 
        UnsupportedCallbackException {

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        if (pc.getIdentifer().equals("joe") {
           if (!pc.getPassword().equals("password")) {
                throw new IOException("wrong password");
           }
        }
    }

}

...

Code Block
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
// Specify our username
outProps.put(WSHandlerConstants.USER, "joe");
// Password type : plain text
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
// for hashed password use:
//properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
// Callback used to retrieve password for given user.
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, 
    ClientPasswordHandler.class.getName());

...

Code Block
java
java
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;

public class ClientPasswordCallback implements CallbackHandler {

    public void handle(Callback[] callbacks) throws IOException, 
        UnsupportedCallbackException {

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        // set the password for our message.
        pc.setPassword("password");
    }

}

...

Code Block
keytool -genkey -alias myAlias -keypass myAliasPassword -keystore \ 
  privatestore.jks \
  -storepass keyStorePassword -dname "cn=myAlias" -keyalg RSA

...

Code Block
keytool -selfcert -alias myAlias -keystore privatestore.jks \ 
    -storepass keyStorePassword -keypass myAliasPassword

...

Code Block
keytool -export -alias myAlias -file key.rsa -keystore privatestore.jks \ 
    -storepass keyStorePassword

...

Code Block
keytool -import -alias myAlias  -file key.rsa -keystore publicstore.jks \ 
    -storepass keyStorePassword

...

Code Block
java
java
outProps.put(WSHandlerConstants.ACTION, "Signature");
outProps.put(WSHandlerConstants.USER, "myAlias");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, 
    ClientCallbackHandler.class.getName());
outProps.put(WSHandlerConstants.SIG_PROP_FILE, "client_sign.properties");

...

Tip
titleTip

For X.509 support you will normally have multiple actions, e.g. Encryption with Signature. For these cases, just space-separate the actions in the ACTION property as follows:

Code Block
java
java
outProps.put(WSHandlerConstants.ACTION, 
    WSHandlerConstants.TIMESTAMP + " " + 
    WSHandlerConstants.SIGNATURE + " " + 
    WSHandlerConstants.ENCRYPT);

Alternatively, you may space-separate the string literals you see above in the Spring configuration (e.g., "Signature Encrypt")

...