我正在尝试将我们当前的应用程序升级到 CXF 3 和 WSS4J 2。这让我很头疼。
客户端的当前应用程序代码:
private void secureWebService( Client client, final Credentials credentials ) {
// set some WS-Security information
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put( WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN );
outProps.put( WSHandlerConstants.USER, credentials.getUsername() );
outProps.put( WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT );
// Callback used to retrieve password for given user.
outProps.put( WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
@Override
public void handle( Callback[] callbacks ) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword( credentials.getPassword() );
}
});
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor( outProps );
client.getOutInterceptors().clear();
client.getOutInterceptors().add( wssOut );
}
在服务器端...
public class ServerPasswordCallback implements CallbackHandler {
public void handle( Callback[] callbacks ) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[0];
boolean result = false;
try {
LoginContext lc = new LoginContext( container, new CallbackHandler() {
public void handle( Callback[] callbacks ) throws IOException, UnsupportedCallbackException {
NameCallback nc = (NameCallback)callbacks[0];
nc.setName( myGetName() );
PasswordCallback pc2 = (PasswordCallback)callbacks[1];
String clientPasssword = pc.getPassword(); //Used to contain the password but is now NULL
pc2.setPassword( clientPasssword.toCharArray() );
}
} );
lc.login();
result = true;
} catch( LoginException le ) {
le.printStackTrace(); //current stack trace is a NULLPointerException since "clientPassword" is NULL
// We haven't authenticated, so false will be returned
} catch( SecurityException se ) {
throw new IOException( "Cannot create LoginContext. " + se.getMessage() );
}
return result;
}
}
我的 JAX-WS 端点配置:
<bean id="wss4jPasswordCallback" class="com.mycompany.webservice.security.ServerPasswordCallback"/>
<jaxws:endpoint id="customerEndpoint" implementor="#customerWebService" address="/Customer">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken"/>
<entry key="passwordType" value="PlainText"/>
<entry key="passwordCallbackRef">
<ref bean="wss4jPasswordCallback"/>
</entry>
</map>
</constructor-arg>
</bean>
<bean class="com.mycompany.webservice.security.Wss4jPrincipalInjectorInterceptor"/>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="com.mycompany.webservice.security.Wss4jPrincipalRemoverInterceptor"/>
</jaxws:outInterceptors>
<jaxws:outFaultInterceptors>
<bean class="com.mycompany.webservice.security.Wss4jPrincipalRemoverInterceptor"/>
</jaxws:outFaultInterceptors>
</jaxws:endpoint>
具体来说,WSPasswordCallback 对象现在传递的是 NULL 而不是过去的密码。根据我的阅读,CXF 只是选择停止这样做,因为有关我将为升级路径做什么的文档不足。什么是升级路径?
另外,我注意到 WSS4J 正在改变它的位置。它已从“org.apache.ws.security”移动到“org.apache.wss4j.common.ext”。我还将所有常量更新为“org.apache.wss4j.dom.WSConstants”和“org.apache.wss4j.dom.handler.WSHandlerConstants”来编译。这也彻底改变了“org.apache.commons.validator.Validator”中旧的“org.apache.ws.security.validate.Validator”类。现在的课已经很不一样了。也许“org.apache.wss4j.dom.validate.KerberosTokenValidator”是新的替代品?同样,我找不到这个事实的文档。
请注意:在迁移到新的 CXF 和 WSS4J 版本之前,这是所有工作代码!