How could I use NTLM Authentication to authenticate via Windows NT Authentication for a servlet based intranet-application ?

Chad Skeeters



[There was a great discussion of this at http://www.jguru.com/faq/viewquestion.jsp?EID=393110 The code below seems to be the final solution, but I recommend reading the thread to make sure, especially since there was much discussion about making it not take 40 seconds to return.

Also, you apparently have to do it during each doPost call??? Not sure what that means, since you can't call sendError during each doPost... Maybe you just have to set the WWW-Authenticate header each time.

Brett Knights also recommends:

The easy way is to use Apache and mod_ntlm. Then req.getRemoteUser() returns the logged in user's name. You can use Apache <Location> directives to limit access to servlet urls. I have used this with JServ and Tomcat.



String auth = request.getHeader("Authorization");
if (auth == null)
  response.setHeader("WWW-Authenticate", "NTLM");
if (auth.startsWith("NTLM "))
  byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
  int off = 0, length, offset;
  if (msg[8] == 1)
    byte z = 0;
    byte[] msg1 = {(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S', (byte)'S', (byte)'P', 
      z,(byte)2, z, z, z, z, z, z, z,(byte)40, z, z, z, 
      (byte)1, (byte)130, z, z,z, (byte)2, (byte)2,
      (byte)2, z, z, z, z, z, z, z, z, z, z, z, z};
    response.setHeader("WWW-Authenticate", "NTLM " + 
       new sun.misc.BASE64Encoder().encodeBuffer(msg1));
  else if (msg[8] == 3)
    off = 30;

    length = msg[off+17]*256 + msg[off+16];
    offset = msg[off+19]*256 + msg[off+18];
    String remoteHost = new String(msg, offset, length);

    length = msg[off+1]*256 + msg[off];
    offset = msg[off+3]*256 + msg[off+2];
    String domain = new String(msg, offset, length);

    length = msg[off+9]*256 + msg[off+8];
    offset = msg[off+11]*256 + msg[off+10];
    String username = new String(msg, offset, length);