Greetings all,  I am attempting to connect to a .NET web service using CXF. 
The requirements for the request's security headers are a Timestamp and a
BinarySecurityToken from an X509 Certificate.  The response only includes a
Timestamp.  I think it is important to note that I do not have any control
over the web service, and we were provided a public key by the vendor to use
for generating the BST, so we do not have the private key, nor a password
for the key.

I have been working from the CXF samples and have read every blog and
mailing list post I can find, but am still having trouble.  I can
successfully generate the Timestamp, and even a UsernameToken (which is not
needed for this project), but I cannot get a BinarySecurityToken to
generate.  When I add the 'Signature' action, I get this
NullPointerException: 

/java.lang.NullPointerException at
org.apache.ws.security.message.WSSecSignature.getSigningCerts(WSSecSignature.java:786)/

I have read other posts that imply this error indicates the keystore either
cannot be found, or cannot be opened.  I have tried putting the keystore in
my JAR as a resource, in the local directory I am running from, in a
different directory, explicitly referencing it in my classpath, etc., but to
no avail.  If I include 'Signature' in the action, I get this error.

I would greatly appreciate any help I can get on this.  Our team attempted
this task using Axis2 for several weeks, and now I'm just starting a new
approach using CXF and need to get it done ASAP.  Now I seem to be at about
the same roadblock the Axis2 route got to... 

Thank you all.

Note: in my source snippets, I have used {} to indicate masked items to
protect sensitive information
*Here is my cxf.xml file:*

/<beans xmlns="http://www.springframework.org/schema/beans";
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xmlns:jaxws="http://cxf.apache.org/jaxws";
   xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://cxf.apache.org/jaxws 
   http://cxf.apache.org/schemas/jaxws.xsd";>

    <jaxws:client name="STWebService-CXF" createdFromAPI="true">
        
        <jaxws:inInterceptors>
            <ref bean="Timestamp_Response"/>
            <bean
class="org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker"/>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <ref bean="Timestamp_Request"/>
        </jaxws:outInterceptors>
    </jaxws:client>

    <bean 
        class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"
        id="Timestamp_Request">
        <constructor-arg>
            <map>
                <entry key="action" value="Timestamp Signature"/>
                <entry key="user" value="{key alias with spaces}"/>
                <entry key="passwordType" value="PasswordDigest"/>
                <entry key="signaturePropFile"
value="clientKeystore.properties"/>
            </map>
        </constructor-arg>
    </bean>

    <bean 
        class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"
        id="Timestamp_Response">
        <constructor-arg>
            <map>
                <entry key="action" value="Timestamp"/>
            </map>
        </constructor-arg>
    </bean>
</beans>
/

*Here is my clientKeystore.properties file:*
/
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.file=public_cert.jks
org.apache.ws.security.crypto.merlin.keystore.password={keystorepass}
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.alias={key alias with spaces}
/

*Here is a snippet of my client, using the CXF-generated client until I can
get it working, then will be moving logic into my own classes:* 
/
...
        SpringBusFactory bf = new SpringBusFactory();
        URL busFile = {Client}.class.getResource("/wssec.xml");
        Bus bus = bf.createBus(busFile.toString());
        BusFactory.setDefaultBus(bus);

                // Out Interceptor
        Map<String, Object> outProps = new HashMap<String, Object>();
        outProps.put("action", "Timestamp Signature");

        outProps.put("passwordType", "PasswordDigest");
        outProps.put("user", "{key alias with spaces}");
        outProps.put("passwordCallbackClass",
"{package}.KeystorePasswordCallback");

        bus.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));

                // In Interceptor
        Map<String, Object> inProps = new HashMap<String, Object>();
        inProps.put("action", "Timestamp");

        bus.getInInterceptors().add(new WSS4JInInterceptor(inProps));

        SynchMethod ss = new SynchMethod(wsdlURL, SERVICE_NAME);
        SynchMethodSoap port = ss.getSynchMethodSoap();

        System.out.println("Invoking web service method...");
        {package}.ArrayOfResponse _return = port.{method}({params...});
        System.out.println("_rerturn=" + _return);
...
/
*
Here is my 'standard' KeystorePasswordCallback class:*
/
package {package}

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
 
/**
 * Really callback for key passwords.  Configure it with a map
 * of key-alias-to-password mappings.  Obviously this could
 * be extended to encrypt or obfuscate these passwords if desired.
 */
public class KeystorePasswordCallback implements CallbackHandler
{
    private Map<String, String> passwords = new HashMap<String, String>();
    /**
     * {@inheritDoc}
     *
     * @see
javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
     */
    public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
        for (Callback callback : callbacks) {
            if (callback instanceof WSPasswordCallback) {
                WSPasswordCallback pc = (WSPasswordCallback)callback;
     
                String pass = passwords.get(pc.getIdentifier());
                if (pass != null) {
                    pc.setPassword(pass);
                    return;
                }
            }
        }
    }
    /**
     * @return the passwords
     */
    public Map<String, String> getPasswords() {
        return passwords;
    }
    /**
     * @param passwords the passwords to set
     */
    public void setPasswords(Map<String, String> passwords) {
        this.passwords = passwords;
    }
}
/



--
View this message in context: 
http://cxf.547215.n5.nabble.com/CXF-client-to-NET-web-service-attempting-to-create-BinarySecurityToken-BST-tp5726168.html
Sent from the cxf-user mailing list archive at Nabble.com.

Reply via email to