2009-02-23 8 views

risposta

1

jespa www.ioplex.com è l'unico che ho incontrato. Mai usato anche se

3

Per essere onesti, non dovresti cercarne uno. Per le tue necessità di SSO dovresti usare kerberos/SPNEGO appropriati invece di NTLM legacy.

Per quella roba non sono necessarie librerie speciali poiché le JVM sono già abilitate per farlo automaticamente. Tutto quello che devi fare è configurare correttamente l'applicazione e le politiche di sicurezza JVM. La documentazione ufficiale di Sun dovrebbe fornirti tutti i dettagli di cui hai bisogno, basta sfogliare la sezione "API di sicurezza".

+5

NTLM non è un meccanismo "legacy". NTLM è richiesto se il client non può ottenere un ticket Kerberos che sfortunatamente accade troppo facilmente. In effetti, Kerberos è piuttosto fragile e difficile da usare al confronto. E NTLMv2 è altrettanto sicuro (128 bit RC4 contro 256 bit AES non ha molta importanza). Se hai bisogno di fare NTLM lato client, JCIFS è completamente funzionale (anche se non è completamente documentato - chiedi sulla mailing list). Se hai bisogno di NTLM lato server come HTTP SSO, Jespa è la strada da percorrere. – user8134

+2

Nota che Jespa non è software libero. –

2

Penso che NTLM venga deprecato in favore di Kerberos/SPNEGO. Dai uno sguardo al progetto SPNEGO HTTP Servlet Filter per vedere se potrebbe soddisfare le tue esigenze.

1

Java Opensource Single Sign On (JOSSO) è a http://www.josso.org/ Hanno una pagina su NTLM, anche se non sono sicuro di quanto funzioni.

11

Waffle - https://github.com/dblock/waffle

Ci sono i filtri, autenticatori, supporta la primavera-sicurezza, ecc solo per Windows, ma non richiede DLL native.

+0

Progetto interessante! –

+1

Fyi, questo progetto è ora in Github - http://github.com/dblock/waffle. –

1

Se non vi dispiace un prodotto commercialmente confezionato, date un'occhiata a: Quest Single Sign On for Java che fornisce supporto per SPNEGO/Kerberos (inclusi siti e protocolli S4U) e NTLM.

3

In realtà jcifs è buono ed è possibile testare facilmente il 4-way handshake localmente con Windows IIS e mantenere vivo il socket Java.

questo 2004 Apache pseudo code è utile per costruire l'algoritmo con JCIFS utilizzando generateType1Msg() e generateType3Msg(), anche Apache promuove un example come alternativa al HttpClient.

Il vecchio codice Apache del 2004 funziona ma l'autenticazione è instabile, si ottiene HTTP/1.1 401 Unauthorized frequentemente, anche questo codice really old di Luigi Dragone non funziona più. D'altra parte, HttpClient di Apache gira senza intoppi, ma l'handshake viene eseguito dietro la scena (fyi HttpClient richiede new NTCredentials() per definire l'autenticazione dell'utente).

Ecco un esempio per testare l'handshake localmente su IIS, sulla porta 81 senza un dominio. È necessario modificare host, port, user e password e intestazioni HTTP in modo appropriato, eventualmente WWW-Authenticate se non si utilizza IIS.

HTTP/1.1 200 OK significa che l'autenticazione è corretta, altrimenti si ottiene 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()); 
    } 
} 
+1

Un esempio che utilizza HttpURLConnection: http://stackoverflow.com/a/34321230/2073804 – ron190