Tomcat and NTLM Authentication

Here is an example of how to use JCIFS to give you transparent user authentication via a built-in servlet filter that it comes bundled with. You will need Tomcat (I am using 5.5.9) or another servlet container, and the JCIFS library in WEB-INF/lib. Here is the contents of web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="TestNTLM" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Servlet 2.4 application</display-name>

<filter>
<filter-name>NtlmHttpFilter</filter-name>
<filter-class>jcifs.http.NtlmHttpFilter</filter-class>

<init-param>
<param-name>jcifs.smb.client.domain</param-name>
<param-value>mydomain</param-value>
</init-param>
<init-param>
<param-name>jcifs.netbios.wins</param-name>
<param-value>192.168.10.24,192.168.10.25</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>NtlmHttpFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>

I have minimally specified a domain name and a couple of WINS servers to use for name resolution. In the index page, I have just put in the following code in a JSP code block:

jcifs.smb.NtlmPasswordAuthentication auth = (jcifs.smb.NtlmPasswordAuthentication)request.getSession().getAttribute("NtlmHttpAuth");
out.println("User: = " + auth.getUsername());
out.println("Domain: = " + auth.getDomain());

This is just to illustrate the kind of information you can retrieve from the session context if JCIFS successfully authenticates the user. The NtlmHttpAuth object is an instance of NtlmPasswordAuthentication that is automatically placed in session scope by the servlet filter.

NT Authentication using JCIFS and SHAJ

Here is another set of examples on how to do native Windows-based user authentication from Java, one using JCIFS and the other using SHAJ. JCIFS has the advantage of not having to install a DLL into the system search path, whereas SHAJ has the advantage of not having to specify a domain controller explicitly in the code. (Incidentally , there is a utility called netdom.exe in the Windows 2000 Resource Kit Tools download that you can use to find your currently active domain controller – just execute netdom /query for the details).

Here is the code:


package uk.co.researchkitchen.auth.nt;

import java.net.UnknownHostException;

import jcifs.UniAddress;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbAuthException;
import jcifs.smb.SmbException;
import jcifs.smb.SmbSession;

import com.cenqua.shaj.Shaj;
import com.cenqua.shaj.log.Log;
import com.cenqua.shaj.log.PrintStreamLog;

public class TestAuth {

public void doAuthJCifs() {
UniAddress mydomaincontroller = null;
try {
mydomaincontroller = UniAddress.getByName( "192.168.0.10" );
} catch (UnknownHostException e) {

e.printStackTrace();
}
NtlmPasswordAuthentication mycreds = new NtlmPasswordAuthentication( "domain", "username", "password" );
try {
SmbSession.logon(mydomaincontroller, mycreds );
} catch( SmbAuthException sae ) {
sae.printStackTrace();
} catch( SmbException se ) {
se.printStackTrace();
}

}

public void doAuthShaj() {
Log.Factory.setInstance(new PrintStreamLog(System.out, true));

if(!Shaj.init()) {
System.err.println("Failed to initialize");
return;
}

System.out.println(Shaj.checkPassword("domain", "username", "password"));

}
}