我发现这些org.apache.cxf
包非常有助于让我不必编写自定义类并且能够坚持使用基本界面。
对于您的实例,该方法可能如下所示:
- 使用
JAX-WS
orwsimport
客户端
- 使用
cxf
WSS4JOutInterceptor
具有动态属性的
- 使用动态
CallbackHandler
类访问密钥库
典型的 ( wsimport
'd) 客户端公共 API 可能如下所示:
public class SomeServiceClient
{
public SomeService getSomeService( URL url )
{
SomeService_Service svc = new SomeService_Service();
SomeService someService = svc.getSomeServicePort();
Client client = ClientProxy.getClient( someService );
Endpoint cxfEP = client.getEndpoint();
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put( WSHandlerConstants.ACTION, "Signature" );
outProps.put( WSHandlerConstants.USER, "foo" );
outProps.put( WSHandlerConstants.PW_CALLBACK_CLASS, SomeClientCallbackHandler.class.getName() );
outProps.put( WSHandlerConstants.SIG_PROP_FILE, "client-sign.properties" );
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor( outProps );
cxfEP.getOutInterceptors().add( wssOut );
return someService;
}
}
您可以提供一些逻辑来确定WSHandlerConstants.USER
要传递的值、PW_CALLBACK_CLASS
使用的值以及SIG_PROP_FILE
使用的值。
属性文件可能如下所示。您可以简单地选择多个文件,或者您可以在类中动态添加这些属性:
# properties for accessing the java keystore using Merlin
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=bar
org.apache.ws.security.crypto.merlin.keystore.alias=foo
org.apache.ws.security.crypto.merlin.keystore.file=foobar.keystore
最后,您CallbackHandler
需要提供您在密钥库中标识的证书别名的密码。这也可能包含一些动态逻辑。
public class SomeClientCallbackHandler implements CallbackHandler
{
@Override
public void handle( Callback[] callbacks ) throws IOException, UnsupportedCallbackException
{
for( Callback thisCallback : callbacks )
{
WSPasswordCallback pwcb = (WSPasswordCallback)thisCallback;
String user = pwcb.getIdentifier();
int usage = pwcb.getUsage();
if( usage == WSPasswordCallback.SIGNATURE )
{
if( "foo".equals( user ) ) pwcb.setPassword( "bar" );
}
}
}
}
最后,与只做一次所需的工作相比,没有太多工作可以让这一切都“动态”地处理多个密钥库。它可能比编写自己的“输入”或“输出”拦截器更可取。