Hi all,
I am trying to implement a web service client that can send soap request
with plain xml string to a web service with WS-Security and apply
WS-Policy to client at runtime. From what I read,
using Dispatcher with interceptor (which loads WS-Policy) is the way to go.
Just to show I have done my home work:
* This thread
http://cxf.547215.n5.nabble.com/Dynamicall-y-define-WS-Policy-in-CXF-td5713085.html
outlines the interceptor approach to load WS-Policy
* This thread
http://cxf.547215.n5.nabble.com/adding-interceptors-to-a-dynamic-jax-ws-dispatcher-client-td5723001.html
seems to confirm interceptor can be dynamically added to a Dispatcher client
* So I look for sample code of using Dispatcher and find
/apache-cxf-2.7.6-src/distribution/src/main/release/samples/in_jvm_transport/src/main/java/demo/colocated/client/DispatchSourceClient.java.
Got it to work by sending plain text request to the sample DoubleIt
web service without any ws-policy.
* Then it dawned on me that I have no idea how the imported WS-Policy
can be applied to a WSDL that has no WS-Policy, after some googling, I
believe
the imported WSDL needs to have format specified in
http://www.w3.org/Submission/WS-PolicyAttachment/
* Next question that came up is how to apply config of encryption &
signing dynamically at runtime. Since it needs to be dynamic, I ruled
out using Spring XML config.
After some googling, I found this excellent blog
http://ashakirin.blogspot.co.nz/2013/04/cxf-security-getting-certificates-from.html
which shows Crypto provider object can be programmatically
set in interceptor, i.e.
public class CustomSecurityInterceptor extends
AbstractPhaseInterceptor<Message> {
public CustomSecurityInterceptor () {
super(Phase.PRE_LOGICAL);
}
@Override
public void handleMessage(Message message) throws Fault {
PKICryptoProvider pkiCryptoProvider = new
PKICryptoProvider();
message.put(SecurityConstants.ENCRYPTION_CRYPTO,
pkiCryptoProvider);
message.put(SecurityConstants.SIGNATURE_CRYPTO,
pkiCryptoProvider);
}
I am assuming this can provide the missing link of configuring keystore
config at runtime. Correct me if wrong.
Right now, my half baked non-working prototype interceptor is
import ...
public class DynamicWSPolicyOutInterceptor extends
AbstractPolicyInterceptor {
public DynamicWSPolicyOutInterceptor() {
super(
InterceptorIdConstants.DYNAMIC_WS_POLICY_OUT_INTERCEPTOR_ID,
Phase.SETUP);
getBefore().add( PolicyOutInterceptor.class.getName() );
}
@Override
protected void handle(Message message) throws PolicyException {
try {
// this will get test WS-Policy data
PolicyUtil policyUtil = new PolicyUtil();
// 1. Build effective policy for response
PolicyBuilder builder =
message.getExchange().getBus().getExtension(PolicyBuilder.class);
Policy effectivePolicy = builder.getPolicy(
policyUtil.getTestPolicyData() ) ;
// 2. Apply effective policy
message.put( PolicyConstants.POLICY_OVERRIDE,
effectivePolicy );
// 3. Apply keystore config like
http://ashakirin.blogspot.co.nz/2013/04/cxf-security-getting-certificates-from.html
// TODO!!
} catch (Exception e) {
throw new PolicyException( e );
e.printStackTrace();
// logging latter
}
}
}
Now the working PolicyUtil is:
import ...
import org.apache.cxf.helpers.IOUtils;
public class PolicyUtil {
// load test data policy file
private InputStream in =
this.getClass().getResourceAsStream("/ws_policy/ws_policy_1");
InputStream getTestPolicyData() {
return in;
}
public static void main(String args[]) throws Exception {
PolicyUtil policyUtil = new PolicyUtil();
String wsPolicy =
IOUtils.toString(policyUtil.getTestPolicyData(), "UTF-8");
System.out.println( wsPolicy ); // OK
}
}
As you can see, it's like playing a painful jig-saw puzzle, so my
ultimate question is, has anyone done something this like already and
care to share sample code?
This can save me or anyone else a lot of pain. :)
If sample code is not possible, then can you at least confirm if I am
still in the right direction and if there is still any road blocks I
haven't hit my head into the wall yet?
Thanks
Regards,
Sam