Someone asked me how they could turn on NT Authentication for web service using Apache Axis (the web service used by ColdFusion). By default Axis uses its own HTTP client code, org.apache.axis.transport.http.HTTPSender, to send the XML/SOAP POST requests to a web service. This uses HTTP 1.0 and generally works file.
Axis also supports the Jakarta Commons HTTPClient library, and has since 1.0. To configure Axis to use this instead of its own library you must edit the client-config.wsdd file used by Axis. It gets found on the classpath and generally you don't actually have one and the one built in to axis.jar gets used.
The interesting line is the http transport. To switch Axis to use the HTTPClient jar, you would change this:
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"></transport>
To this:
<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender"></transport>
Once you have this code configured, Axis will use the HTTPClient library for it HTTP needs. Since the HTTPClient library supports NT Authentication, you just set the username/password on the Stub object as you would normally do for (say) Basic Authentication and it will just work. If you are talking to a .NET web service, you are done.
BUT switching the line in the client-config.wsdd file alone doesn't do the trick if you are talking to a ColdFusion web service. Talking to a ColdFusion web service via Apache, you will get an "411 - length required" error back that looks like this:
The Apache JRun connector doesn't allow chunked encoding without a content length (generally true for all general pupose connectors, including mod_python) and the CommonsHTTPSender class in Axis does not provide a content-length. Go figure.
Axis also supports the Jakarta Commons HTTPClient library, and has since 1.0. To configure Axis to use this instead of its own library you must edit the client-config.wsdd file used by Axis. It gets found on the classpath and generally you don't actually have one and the one built in to axis.jar gets used.
The interesting line is the http transport. To switch Axis to use the HTTPClient jar, you would change this:
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"></transport>
To this:
<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender"></transport>
Once you have this code configured, Axis will use the HTTPClient library for it HTTP needs. Since the HTTPClient library supports NT Authentication, you just set the username/password on the Stub object as you would normally do for (say) Basic Authentication and it will just work. If you are talking to a .NET web service, you are done.
BUT switching the line in the client-config.wsdd file alone doesn't do the trick if you are talking to a ColdFusion web service. Talking to a ColdFusion web service via Apache, you will get an "411 - length required" error back that looks like this:
The Apache JRun connector doesn't allow chunked encoding without a content length (generally true for all general pupose connectors, including mod_python) and the CommonsHTTPSender class in Axis does not provide a content-length. Go figure.
Using the built-in JRun web server you get a a "content not allowed in prolog" error because it appears the JRun web service doesn't understand chunked transfer encoding. Go figure again.
I didn't try it with IIS. My guess it that it might work.
To solution? Turn off the chunked encoding, which you can do by setting a property on the web service object in CFML like this:
ws = CreateObject("webservice", "http://localhost/ws/service.cfc?wsdl");
httpheaders = CreateObject("java", "java.util.Hashtable").init();
httpheaders.put("chunked", "false");
ws._setProperty("HTTP-Request-Headers", httpheaders);
result= ws.myOperation();
The Apache code wants a Hashtable, where it should just look for a Map, so you can't just use a CFML structure for the value of the HTTP-Request-Headers.
httpheaders = CreateObject("java", "java.util.Hashtable").init();
httpheaders.put("chunked", "false");
ws._setProperty("HTTP-Request-Headers", httpheaders);
result= ws.myOperation();
The Apache code wants a Hashtable, where it should just look for a Map, so you can't just use a CFML structure for the value of the HTTP-Request-Headers.