Introduction:
This BOK details how to get a Java-based web-application to negotiate with a IE web client for username and domain information. This is a common requirement for web-based applications especially ones that do not want to bore users with a login page. IE will negotiate a user’s password hashes with the webserver, which checks their authenticity against a windows domain controller. If valid, the user’s username and domain will be accessible to the webserver servlets.
NTLM Authentication and how we achieve it:
The method HttpServletRequest.getRemoteUser() should return the username of the person using the browser which fired a request to this Servlet.
This method, however works correctly only if the user has been authenticated first by a webserver authentication scheme -
which could be BASIC,DIGEST or CLIENT-CERT. This is the kind of setup the the Apache webserver provides, giving a challenge-response, username-password method of authentication.
What we do here is use a Servlet filter provided as part of the open-source jCIFS package, to get an IE user's username and domain.
This filter will take the trouble of intercepting user requests, asking IE for the user's password hashes,validating them against a windows domain controller and enabling HttpServletRequest.getRemoteUser() to return the windows user id.
Please note this method will not work for non-IE clients, simply because this is a proprietary extension by Microsoft.
For other browsers you will have to rely on BASIC or certificate-based authentication.
How to setup your web application:
First, we need to download a jcifs jar from http://jcifs.samba.org. I have tested this with jcifs version 0.7.14.jCIFS is from the makers of Samba and provides APIs to access Windows shares, networks and the ability to authenticate against a Windows domain controller. Place this jar under WEB-INF/lib of your web application. There is a filter called jcifs.http.NtlmHttpFilter which implements all the wizadry above. You need to register it in your application's web.xml descriptor:
<web-app>
...
<!-- NTLM HTTP Authentication only works with MSIE -->
<filter>
<filter-name>NTLM HTTP Authentication Filter</filter-name>
<filter-class>jcifs.http.NtlmHttpFilter</filter-class>
<!-- CCD will help you with a PDC and WINS server ip at your location. -->
<init-param>
<param-name>jcifs.http.domainController</param-name>
<param-value>192.168.170.5</param-value>
</init-param>
<init-param>
<param-name>jcifs.netbios.wins</param-name>
<param-value>192.168.166.13</param-value>
</init-param>
</filter>
<!-- This is the url under which we need access to the username and domain. -->
<filter-mapping>
<filter-name>NTLM HTTP Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
That's it. Now all IE requests to your webserver urls as specified in the web.xml entries are negotiated so that you can call a HttpServletRequest.getRemoteUser() to get the remote user's username in the form.
DOMAIN\username.
Please note at no point will a password dialog pop up for the user, the password hashes are picked from IE and validated with the domain controller.
Example code for a servlet :
public void doGet( HttpServletRequest req, HttpServletResponse resp ) throws IOException, ServletException
{
PrintWriter out = resp.getWriter();
resp.setContentType( “text/html” );
out.println( “<HTML><HEAD><TITLE>NTLM HTTP Authentication Example</TITLE></HEAD><BODY>” );
out.println( “<h2>NTLM HTTP Authentication Example</h2>” );
out.println( req.getRemoteUser() + ” logged in” );
}
If the filter has not been configured properly, a null will be printed for the above call to req.getRemoteUser().
References:
Tags: Add new tag, HttpServletRequest.getRemoteUser(), IE, JSP FAQ, NTLM Authentication, oracle, scripts, servlet questions, Servlets, Servlets FAQ, technical FAQ, technical tips, Web applications