2009-02-23 13 views

Odpowiedz

1

jespa www.ioplex.com to jedyny, z którym się zetknąłem. Nigdy nie był używany, ale

3

Szczerze mówiąc, nie powinieneś go szukać. Dla potrzeb SSO powinieneś użyć właściwego Kerberos/SPNEGO zamiast dotychczasowego NTLM.

Do tego nie są potrzebne specjalne biblioteki, ponieważ maszyny JVM są już automatycznie włączone. Wszystko, co musisz zrobić, to poprawnie skonfigurować swoją aplikację i zasady bezpieczeństwa JVM. Oficjalna dokumentacja firmy Sun powinna zawierać wszystkie potrzebne informacje, wystarczy przejrzeć sekcję "Security APIs".

+5

NTLM nie jest mechanizmem "starszym". NTLM jest wymagany, jeśli klient nie może uzyskać biletu Kerberos, który niestety zdarza się zbyt łatwo. W rzeczywistości Kerberos jest raczej kruchy i trudny w użyciu w porównaniu. NTLMv2 jest tak samo bezpieczny (128-bitowy RC4 w porównaniu do 256-bitowego AES naprawdę nie ma większego znaczenia). Jeśli potrzebujesz NTLM po stronie klienta, JCIFS jest w pełni funkcjonalny (choć nie jest w pełni udokumentowany - zapytaj na liście mailingowej). Jeśli potrzebujesz NTLM po stronie serwera, na przykład do SSO HTTP, Jespa jest drogą do zrobienia. – user8134

+2

Należy pamiętać, że Jespa nie jest wolnym oprogramowaniem. –

2

Myślę, że NTLM jest przestarzałe na rzecz Kerberos/SPNEGO. Spójrz na projekt SPNEGO HTTP Servlet Filter, aby sprawdzić, czy może on pasować do twoich potrzeb.

1

Java Opensource Single Sign On (JOSSO) ma numer http://www.josso.org/ Ma stronę na NTLM, chociaż nie jestem pewien, jak dobrze działa.

11

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

Posiada filtry, uwierzytelniające, wspiera wiosna-security itp tylko w systemie Windows, ale nie wymaga natywnych bibliotek DLL.

+0

Interesujący projekt! –

+1

Fyi, ten projekt jest teraz w Github - http://github.com/dblock/waffle. –

1

Jeśli nie masz nic przeciwko produktowi pakowanemu komercyjnie, spójrz na: Quest Single Sign On for Java, która zapewnia obsługę SPNEGO/Kerberos (w tym witryn i protokołów S4U), a także NTLM.

3

Właściwie jcifs jest dobry i można łatwo przetestować 4-way handshake lokalnie za pomocą Windows IIS i utrzymywać przy życiu gniazdo Java.

to 2004 Apache pseudo code jest przydatna do budowy algorytmu z wykorzystaniem generateType1Msg() JCIFS i generateType3Msg() nawet Apache promuje example jako alternatywa dla HttpClient.

Stary kod Apache z 2004 działa, ale uwierzytelnienie jest niestabilne, często dostajesz HTTP/1.1 401 Unauthorized, również ten kod really old z Luigi Dragone już nie działa. Z drugiej strony HttpClient Apache działa płynnie, ale uzgadnianie odbywa się za sceną (fyi. HttpClient wymaga new NTCredentials() do zdefiniowania uwierzytelniania użytkownika).

Oto przykład, aby przetestować handshake lokalnie na IIS, na porcie 81 bez domeny. Musisz zmienić odpowiednio nagłówki host, port, user i password i HTTP, ewentualnie WWW-Authenticate, jeśli nie korzystasz z IIS.

HTTP/1.1 200 OK oznacza, że ​​uwierzytelnienie jest poprawne, w przeciwnym razie otrzymasz 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

Przykład użycia HttpURLConnection: http://stackoverflow.com/a/34321230/2073804 – ron190