tutorial - sistema de biblioteca en java y mysql
Alternativas para la biblioteca JCIFS NTLM (7)
¿Hay alguna alternativa para la biblioteca JCIFS NTLM?
jespa www.ioplex.com es la única con la que me he encontrado. Nunca lo usé, aunque
Para ser honesto, no deberías buscar uno. Para sus necesidades de SSO, debe usar kerberos / SPNEGO correctos en lugar del NTLM heredado.
Para eso no necesita bibliotecas especiales ya que las JVM ya están habilitadas para hacerlo automáticamente. Todo lo que tiene que hacer es configurar su aplicación y las políticas de seguridad de JVM correctamente. La documentación oficial de Sun debe darle todos los detalles que necesita, solo busque la sección "API de seguridad".
Creo que NTLM se está desaprobando a favor de Kerberos / SPNEGO. Eche un vistazo al proyecto SPNEGO HTTP Servlet Filter para ver si se ajusta a sus necesidades.
El inicio de sesión único de Java Opensource (JOSSO) está en http://www.josso.org/ Tienen una página en NTLM, aunque no estoy seguro de qué tan bien funcione.
Si no le importa un producto comercialmente empaquetado, eche un vistazo a: Quest Single Sign On para Java, que brinda soporte para SPNEGO / Kerberos (incluidos los sitios y protocolos S4U) y NTLM.
En realidad, jcifs es bueno y puedes probar fácilmente el apretón de manos de 4 vías a nivel local con Windows IIS y un socket Keep alive java.
Este pseudo código Apache 2004 es útil para construir el algoritmo con jcifs utilizando generateType1Msg()
y generateType3Msg()
, incluso Apache promueve un ejemplo como alternativa a HttpClient.
El antiguo código Apache de 2004 funciona, pero la autenticación es inestable, se obtiene HTTP/1.1 401 Unauthorized
frecuencia, y este código realmente antiguo de Luigi Dragone ya no funciona. Por otro lado, el HttpClient de Apache funciona sin problemas, pero el protocolo de enlace se realiza detrás de la escena (por ejemplo, HttpClient requiere new NTCredentials()
para definir la autenticación del usuario).
Aquí hay un ejemplo para probar el apretón de manos localmente en IIS, en el puerto 81 sin un dominio. Debe cambiar el host
, el port
, el user
, user
password
y los encabezados HTTP de forma adecuada, eventualmente WWW-Authenticate
si no está utilizando IIS.
HTTP/1.1 200 OK
significa que la autenticación es correcta; de lo contrario, obtiene HTTP/1.1 401 Unauthorized
.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import jcifs.ntlmssp.NtlmFlags;
import jcifs.ntlmssp.Type1Message;
import jcifs.ntlmssp.Type2Message;
import jcifs.ntlmssp.Type3Message;
import jcifs.util.Base64;
import org.apache.http.impl.auth.NTLMEngineException;
public class TestNTLM {
public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException {
Socket s = new Socket("127.0.0.1", 81);
s.setKeepAlive(true);
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(is));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(os));
String host = "127.0.0.1:81";
String hostDomain = "";
String user = "My_Windows_Username";
String password = "My_Windows_Password";
w.write("GET http://127.0.0.1:81/ HTTP/1.1/n");
w.write("Host: 127.0.0.1:81/n");
w.write("Authorization: NTLM " + TestNTLM.generateType1Msg(hostDomain, host) + "/n/n");
System.out.println("[First Message Sent]");
w.flush();
String resp = "", line = "";
int contentLength = 0;
while((line = r.readLine()) != null){
if(line.length() == 0)
break;
System.out.println(line);
if(line.startsWith("Content-Length"))
contentLength = Integer.parseInt(line.substring(line.indexOf(":") + 1).trim());
else if(line.startsWith("WWW-Authenticate"))
resp = line.substring(line.indexOf(":") + 1).trim();
}
r.skip(contentLength);
System.out.println("/n[Second Message Received]");
System.out.println("Proxy-Authenticate: " + resp);
resp = resp.substring(resp.indexOf(" ")).trim();
w.write("GET http://127.0.0.1:81/ HTTP/1.1/n");
w.write("Host: 127.0.0.1:81/n");
w.write("Authorization: NTLM " + TestNTLM.generateType3Msg(user, password, hostDomain, host, new String(resp)) + "/n/n");
w.flush();
System.out.println("/n[Third Message Sent]");
while((line = r.readLine()) != null){
System.out.println(line);
if(line.length() == 0)
break;
}
}
private static final int TYPE_1_FLAGS =
NtlmFlags.NTLMSSP_NEGOTIATE_56 |
NtlmFlags.NTLMSSP_NEGOTIATE_128 |
NtlmFlags.NTLMSSP_NEGOTIATE_NTLM2 |
NtlmFlags.NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
NtlmFlags.NTLMSSP_REQUEST_TARGET;
public static String generateType1Msg(final String domain, final String workstation)
throws NTLMEngineException {
final Type1Message type1Message = new Type1Message(TYPE_1_FLAGS, domain, workstation);
return Base64.encode(type1Message.toByteArray());
}
public static String generateType3Msg(final String username, final String password,
final String domain, final String workstation, final String challenge)
throws NTLMEngineException {
Type2Message type2Message;
try {
type2Message = new Type2Message(Base64.decode(challenge));
} catch (final IOException exception) {
throw new NTLMEngineException("Invalid NTLM type 2 message", exception);
}
final int type2Flags = type2Message.getFlags();
final int type3Flags = type2Flags
& (0xffffffff ^ (NtlmFlags.NTLMSSP_TARGET_TYPE_DOMAIN | NtlmFlags.NTLMSSP_TARGET_TYPE_SERVER));
final Type3Message type3Message = new Type3Message(type2Message, password, domain,
username, workstation, type3Flags);
return Base64.encode(type3Message.toByteArray());
}
}
Waffle - https://github.com/dblock/waffle
Tiene filtros, autenticadores, admite seguridad de primavera, etc. Solo para Windows, pero no requiere archivos DLL nativos.