I'm programming NTLM authentication in Java EE. If "windows integrated authentication" is enabled in the browser like Internet Explorer so everything works good (the browser send user's name to the server ). But if "windows integrated authentication" is disabled like Mozilla firefox, the browser display an at authentication form where user have to enter his login and password. My problem is: In the second case when the user enter his login and password, i can get login from the server side, but i can't get password. I have to get a password otherwise every user only just have to know the username of another user to authenticate in his place.
My code below:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* NTLM
*/
String auth = request.getHeader("Authorization");
//No NTLM authentification
if (auth == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM");
return;
}
//check what client sent
if (auth.startsWith("NTLM")) {
byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;
if (msg[8] == 1) {
off = 18;
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};
// send ntlm type2 msg
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
return;
} //receive ntlm type 3 msg
else if (msg[8] == 3) {
off = 30;
//username
length = msg[off + 9] * 256 + msg[off + 8];
offset = msg[off + 11] * 256 + msg[off + 10];
username = new String(msg, offset, length);
//remoteHost
length = msg[off + 17] * 256 + msg[off + 16];
offset = msg[off + 19] * 256 + msg[off + 18];
remoteHost = new String(msg, offset, length);
//domain
length = msg[off + 1] * 256 + msg[off];
offset = msg[off + 3] * 256 + msg[off + 2];
domain = new String(msg, offset, length);
} else {
return;
}
}
/**
* END NTLM
*/
request.setAttribute("username", username);
request.setAttribute("remoteHost", remoteHost);
request.setAttribute("domain", domain);
request.setAttribute("ipAdress", request.getRemoteAddr());
request.setAttribute("remotePort", request.getRemotePort());
request.setAttribute("protocol", request.getProtocol());
this.getServletContext().getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);
You need to send the following HTTP header in order to get the password from client:
WWW-Authenticate: Basic realm="insert realm"
The problem is how to decide whether to request NTLM or Basic authentication. One approach is to first ask for NTLM, in case the response cannot be verified, then ask for Basic (and therefore get the password). You could also detect on server side which browser your client uses or from which IP is he accessing and decide whether to use NTLM or Basic based on this data.
Some browsers can also handle getting both NTLM and Basic headers at the same time and decide on which one to use based on their capabilities:
WWW-Authenticate: NTLM
WWW-Authenticate: Basic realm="insert realm"
String auth = request.getHeader("Authorization");
//No NTLM authentification
if (auth == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM");
return;
}
//when the integrated authentication is disabled
//basic authentication
if((auth !=null)&&(!auth.startsWith("NTLM")))
{
{
StringTokenizer st = new StringTokenizer(auth);
if(st.hasMoreTokens()){
String basic = st.nextToken();
if (basic.equalsIgnoreCase("Basic")) {
try{
String credentials = new String(Base64.decode(st.nextToken()));
int p = credentials.indexOf(":");
if (p != -1) {
username = credentials.substring(0, p).trim();
password = credentials.substring(p + 1).trim();
}
}catch(Exception e){
}
}
}
}
}
//check what client sent
if (auth.startsWith("NTLM")) {
byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;
if (msg[8] == 1) {
off = 18;
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};
// send ntlm type2 msg
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "NTLM " + new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
return;
} //receive ntlm type 3 msg
else if (msg[8] == 3) {
off = 30;
//username
length = msg[off + 9] * 256 + msg[off + 8];
offset = msg[off + 11] * 256 + msg[off + 10];
username = new String(msg, offset, length);
//remoteHost
length = msg[off + 17] * 256 + msg[off + 16];
offset = msg[off + 19] * 256 + msg[off + 18];
remoteHost = new String(msg, offset, length);
//domain
length = msg[off + 1] * 256 + msg[off];
offset = msg[off + 3] * 256 + msg[off + 2];
domain = new String(msg, offset, length);
} else {
return;
}
}
Why are you wasting your time with proprietary stuff? Use Kerberos .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.