Usando la autenticación NTLM en aplicaciones Java

Deseo utilizar la autenticación de Windows NTLM en mi aplicación Java para autenticar a los usuarios de la intranet de forma transparente. Los usuarios no deberían notar ninguna autenticación si usan sus navegadores (inicio de sesión único).

He encontrado algunas librerías con soporte NTLM, pero no sé cuál usar:

  • http://spnego.sourceforge.net/
  • http://sourceforge.net/projects/ntlmv2auth/
  • http://jcifs.samba.org/
  • http://www.ioplex.com/jespa.html
  • http://www.luigidragone.com/software/ntlm-authentication-in-java/

¿Alguna sugerencia por dónde empezar?

Fuera de la lista anterior, solo ntlmv2-auth y Jespa admiten NTLMv2. Jespa es viable pero comercial. ntlmv2-auth No lo he intentado, pero está basado en el código de Liferay, que he visto antes.

‘ntlm-authentication-in-java’ es solo NTLMv1, que es antiguo, inseguro y funciona en una cantidad cada vez menor de entornos a medida que las personas actualizan a las versiones más nuevas de Windows. JCIFS solía tener un filtro de autenticación HTTP NTLMv1, pero se eliminó en versiones posteriores, ya que la forma en que se implementó equivale a un ataque de hombre en el medio en el protocolo inseguro. (Lo mismo parece ser cierto para ‘ntlm-authentication-in-java’).

El proyecto ‘spnego’ es Kerberos no NTLM. Si desea replicar IWA completo como lo hace IIS, necesitaría admitir tanto NTLMv2 como Kerberos (autenticación ‘NTLM’, ‘Negociar’ auth, NTLMSSP-en-SPNego auth y NTLM-enmascaramiento-como-negociación auth).

El guión de Luigi Dragone es muy antiguo y parece que siempre falla.

HttpURLConnection puede funcionar con NTLM si agrega jcifs de biblioteca, este ejemplo funciona con el último jcifs-1.3.18 :

 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import org.apache.http.impl.auth.NTLMEngineException; public class TestNTLMConnection { public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException { // Method 1 : authentication in URL jcifs.Config.registerSmbURLHandler(); URL urlRequest = new URL("http://domain%5Cuser:pass@127.0.0.1/"); // or Method 2 : authentication via System.setProperty() // System.setProperty("http.auth.ntlm.domain", "domain"); // System.setProperty("jcifs.smb.client.domain", "domain"); // System.setProperty("jcifs.smb.client.username", "user"); // System.setProperty("jcifs.smb.client.password", "pass"); // Not verified // System.setProperty("jcifs.netbios.hostname", "host"); // System.setProperty("java.protocol.handler.pkgs", "jcifs"); // URL urlRequest = new URL("http://127.0.0.1:8180/simulate_get.php"); HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection(); StringBuilder response = new StringBuilder(); try { InputStream stream = conn.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(stream)); String str = ""; while ((str = in.readLine()) != null) { response.append(str); } in.close(); System.out.println(response); } catch(IOException err) { System.out.println(err); } finally { Map msgResponse = new HashMap(); for (int i = 0;; i++) { String headerName = conn.getHeaderFieldKey(i); String headerValue = conn.getHeaderField(i); if (headerName == null && headerValue == null) { break; } msgResponse.put(headerName == null ? "Method" : headerName, headerValue); } System.out.println(msgResponse); } } } 

Y si tiene curiosidad sobre el contenido de cada apretón de manos, puede encontrar otro ejemplo usando jcifs y Socket en este hilo .

Relativamente a la lista que me dieron, iría con JCIFS . La biblioteca está madura y su documentación es buena. Para colmo, tuvieron lanzamientos bastante regulares, y el último fue noviembre de 2011.

Personal Experience : fue bastante fácil comenzar en comparación con otros que he probado (spnego y ntmv2auth)

Ref: https://jcifs.samba.org/src/docs/faq.html#ntlmv2

P: ¿JCIFS es compatible con NTLMv2?
A: Sí. A partir de 1.3.0, JCIFS es totalmente compatible con NTLMv2 y lo usa de forma predeterminada.

Nota: El filtro HTTP SSO de NTLM que solía incluirse con JCIFS no puede admitir NTLMv2.