Search code examples
javaweb-servicescxfntlmcxf-client

Apache CXF 3.1.6 webservice client - NTLM Authentication


I am trying to connect to service authenticated with NTLM. I have client generated with maven cxf plugin wsdl2java. I got an exception: org.apache.cxf.ws.policy.PolicyException: None of the policy alternatives can be satisfied. Maybe there is another way to do this authentication.

public class UFENTLM1Test {

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, InstantiationException {
    System.out.println("UFE SERVICE TEST (NTLM No1 WRAPPER)");
    System.out.println("PARAMS: " + args[1] + " " + args[2] + " ");
    System.out.println("START");

    Authenticator.setDefault(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return (new PasswordAuthentication(args[1], args[2].toCharArray()));
        }
    });
    //LAMAccountAPI service = new LAMAccountAPI();

    URL url = LAMAccountAPI.class.getClassLoader().getResource("wsdl/ufe/ufe_account.wsdl");

    // TO AVOID SEIStub cannot be cast to ClientProxy
    LAMAccountAPI service = new LAMAccountAPI(url, LAMAccountAPI.SERVICE);
    Field delegateField = Service.class.getDeclaredField("delegate");
    delegateField.setAccessible(true);
    ServiceDelegate previousDelegate = (ServiceDelegate) delegateField.get(service);
    if (!previousDelegate.getClass().getName().contains("cxf")) {
        ServiceDelegate serviceDelegate = ((Provider) Class.forName("org.apache.cxf.jaxws.spi.ProviderImpl").newInstance())
                .createServiceDelegate(url, LAMAccountAPI.SERVICE, service.getClass());
        delegateField.set(service, serviceDelegate);
    }

    ILAMZarzadzanieKontem port = service.getBasicHttpBindingILAMZarzadzanieKontem();

    // Many various tryings
    Client client = ClientProxy.getClient(port);
    HTTPConduit http = (HTTPConduit) client.getConduit();
    http.getAuthorization().setUserName(args[1]);
    http.getAuthorization().setPassword(args[2]);
    AuthorizationPolicy policy = new AuthorizationPolicy();
    policy.setUserName(args[1]);
    policy.setPassword(args[2]);
    http.setAuthorization(policy);
    HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
    httpClientPolicy.setConnectionTimeout(36000);
    httpClientPolicy.setAllowChunking(false);
    http.setClient(httpClientPolicy);

    List<Konto> accounts = null;
    try {
        accounts = port.pobierzKonta().getKonto();
    } catch (ILAMZarzadzanieKontemPobierzKontaSOAPExceptionFaultMessage | ILAMZarzadzanieKontemPobierzKontaDataConversionExceptionFaultMessage ilamZarzadzanieKontemPobierzKontaSOAPExceptionFaultMessage) {
        ilamZarzadzanieKontemPobierzKontaSOAPExceptionFaultMessage.printStackTrace();
    }
}

And policy definition from WSDL:

<wsp:Policy wsu:Id="BasicHttpBinding_ILAMZarzadzanieKontem_policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <http:NtlmAuthentication xmlns:http="http://schemas.microsoft.com/ws/06/2004/policy/http"/>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>

Finally, full stacktrace:

UFE SERVICE TEST (NTLM No1 WRAPPER)
START
lip 01, 2016 2:38:20 PM [com.sun.xml.internal.ws.policy.EffectiveAlternativeSelector]  selectAlternatives
WARNING: WSP0075: Policy assertion "{http://schemas.microsoft.com/ws/06/2004/policy/http}NtlmAuthentication" was evaluated as "UNKNOWN".
lip 01, 2016 2:38:20 PM [com.sun.xml.internal.ws.policy.EffectiveAlternativeSelector]  selectAlternatives
WARNING: WSP0019: Suboptimal policy alternative selected on the client side with fitness "UNKNOWN".
lip 01, 2016 2:38:21 PM org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
INFO: Creating Service {http://tempuri.org/}LAMAccountAPI from WSDL: file:/C:/dev/work/compfort/warta/3639/iiq-connector/target/classes/wsdl/ufe/ufe_account.wsdl
lip 01, 2016 2:38:22 PM org.apache.cxf.ws.policy.AssertionBuilderRegistryImpl handleNoRegisteredBuilder
WARNING: No assertion builder for type {http://schemas.microsoft.com/ws/06/2004/policy/http}NtlmAuthentication registered.
Exception in thread "main" org.apache.cxf.ws.policy.PolicyException: None of the policy alternatives can be satisfied.
    at org.apache.cxf.ws.policy.EndpointPolicyImpl.chooseAlternative(EndpointPolicyImpl.java:172)
    at org.apache.cxf.ws.policy.EndpointPolicyImpl.finalizeConfig(EndpointPolicyImpl.java:146)
    at org.apache.cxf.ws.policy.EndpointPolicyImpl.initialize(EndpointPolicyImpl.java:142)
    at org.apache.cxf.ws.policy.PolicyEngineImpl.createEndpointPolicyInfo(PolicyEngineImpl.java:604)
    at org.apache.cxf.ws.policy.PolicyEngineImpl.getEndpointPolicy(PolicyEngineImpl.java:316)
    at org.apache.cxf.ws.policy.PolicyEngineImpl.getClientEndpointPolicy(PolicyEngineImpl.java:303)
    at org.apache.cxf.ws.policy.PolicyDataEngineImpl.getClientEndpointPolicy(PolicyDataEngineImpl.java:61)
    at org.apache.cxf.transport.http.HTTPConduit.updateClientPolicy(HTTPConduit.java:318)
    at org.apache.cxf.transport.http.HTTPConduit.updateClientPolicy(HTTPConduit.java:338)
    at org.apache.cxf.transport.http.HTTPConduit.getClient(HTTPConduit.java:873)
    at org.apache.cxf.transport.http.HTTPConduit.configureConduitFromEndpointInfo(HTTPConduit.java:360)
    at org.apache.cxf.transport.http.HTTPConduit.finalizeConfig(HTTPConduit.java:440)
    at org.apache.cxf.transport.http.HTTPTransportFactory.getConduit(HTTPTransportFactory.java:242)
    at org.apache.cxf.binding.soap.SoapTransportFactory.getConduit(SoapTransportFactory.java:226)
    at org.apache.cxf.binding.soap.SoapTransportFactory.getConduit(SoapTransportFactory.java:233)
    at org.apache.cxf.endpoint.AbstractConduitSelector.createConduit(AbstractConduitSelector.java:145)
    at org.apache.cxf.endpoint.AbstractConduitSelector.getSelectedConduit(AbstractConduitSelector.java:107)
    at org.apache.cxf.endpoint.UpfrontConduitSelector.selectConduit(UpfrontConduitSelector.java:77)
    at org.apache.cxf.endpoint.ClientImpl.getConduit(ClientImpl.java:845)
    at pl.warta.connector.ufe.test.UFENTLM1Test.main(UFENTLM1Test.java:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Solution

  • It is a problem with the proprietary ws-policy tag http:NtlmAuthentication. The problem is that cxf tries to automatically fulfill ws-policy requirements out of the box. Since this tag is proprietary and non-standard it fails, hence the exception.

    Remove this (whole) policy from your wsdl and generate the client once more without this policy. After that the ntlm authentication should work.