简体   繁体   中英

how to change wsse:KeyIdentifier to wsse:Reference with CXF

I'm using CXF 3.1.5, trying to send a request to a STS server, the STS server has a policy , the related part is as following

<wsp:Policy>
    <sp:RequireThumbprintReference />
    <sp:WssX509V3Token10 />
</wsp:Policy>

so in the request CXF sends to the STS server, the signature key looks like that:

<wsse:SecurityTokenReference wsu:Id="...">
    <wsse:KeyIdentifier EncodingType="..."ValueType="...#ThumbprintSHA1">...</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>

but I want to change the SecurityTokenReference into that

<wsse:SecurityTokenReference>
    <wsse:Reference URI="..." ValueType="...#**X509v3**"/>
</wsse:SecurityTokenReference>

it refers to the BinarySecurityToken which is a X.509 Certificate

So what should I do? I found something about PolicyBasedWSS4JOutInterceptor and PolicyBasedWSS4JInInterceptor , but don't known how they works.

Thanks a lots!

You need a certificate issued by a CA accepted by your server to sign the SOAP request. You can use CXF with WSS4JOutInterceptor

This is the configuration to use WSS4J with CXF. Omit the part of creating the keystore

Set WSS4J properties (adjust to your policy)

outProps.put("action", "Signature");
outProps.put("user", certificateAlias);
outProps.put("passwordType", "PasswordText");
outProps.put("signaturePropFile", propertiesFile);
outProps.put("signatureKeyIdentifier","DirectReference");
outProps.put("passwordCallbackRef",clientPasswordCallback);

propertiesFile contains the path to a properties file where is configured the path to the keystore

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.file=keystore.jks

ClientPasswordCallback performs a callback from wss4j to get the password of the certificate

public class ClientPasswordCallback implements CallbackHandler {
   String password = ...; //Configure the password

   public void handle(Callback[] callbacks) {
     for (int i = 0; i < callbacks.length; i++) {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
        pc.setPassword(password);
      }
   }
}

Configure the CXF client using the WebService port

Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);

//Include LoggingOutInterceptor to log the soap message
cxfEndpoint.getOutInterceptors().add(new LoggingOutInterceptor());

And finally call your service

port.myService();   

@pedrofb, thanks a lot for your help. unfortunately, I still got two BinarySecurityToken Elements and I couldn't use an alternative policy file.

but I found a solution here: How to get incoming & outgoing soap xml in a simple way using Apache CXF?

It provides a solution for me to edit the soap envelop right before CXF sends it out. It's not very good, but it's the best solution I got.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM