2015-03-06 30 views
9

Próbuję zmienić aplikację z użycia java7u51 na java8u40, ale uwierzytelnianie SSO nie działa. Klient się nie zmienił, korzysta z wywołań okien JNA (Secur32.INSTANCE.InitializeSecurityContext), ale serwer nie akceptuje już biletu. Kod serwera nie został zmieniony, ale używa standardowych bibliotek java, które wydają się być zmienione. Serwer działa pod Linuksem.Zmiana uwierzytelnienia serwera Kerberos/SPNEGO w języku Java8

Kod serwera znajduje się poniżej. Na moim komputerze z systemem Windows piszę plik zawierający ten bilet, dzięki czemu mogę uruchomić poniższy kod do testowania. Mam ustawiony bardzo wysoki zegar tak, że mogę przetestować bilet. Napisałem bilet klienta za pomocą java7u51 na wszelki wypadek, ale to nie pomogło. Ten sam bilet działa poprawnie, gdy uruchomię poniższy kod serwera w java7.

Bit, który zawodzi, polega na tym, że isEstablished zwraca wartość false. Nie ma przydatnych informacji debugowania. isEstablished Zwrot fałszywego implikuje, że potrzeba więcej rund, ale tak się nie stało i nie sądzę, że tak powinno być.

Czy ktoś wie, dlaczego to się nie powiedzie w java8? To nie jest tylko problem z aktualizacją 40, ale nie działa z wcześniejszymi wersjami java 8.

dzięki

Properties.setProp("sun.security.krb5.debug", "true") 
Properties.setProp("java.security.krb5.realm", "xxxx") 
Properties.setProp("java.security.krb5.kdc", "xxxx") 
Properties.setProp("java.security.krb5.conf", url(getClass, "/krb5.conf.auth").toExternalForm) 
Properties.setProp("java.security.auth.login.config", url(getClass, "/jaas.conf.auth").toExternalForm) 
Properties.setProp("javax.security.auth.useSubjectCredsOnly", "true") 

val loginCtx: LoginContext = new LoginContext("Server", new LoginCallbackHandler(password)) 
loginCtx.login() 
val subject = loginCtx.getSubject 
val ticket = StringIO.readStringFromFile(new File("/tmp/ticket")) 
val decoder: BASE64Decoder = new BASE64Decoder 
val serviceTicket = decoder.decodeBuffer(ticket) 

val user = Subject.doAs(subject, new PrivilegedAction[Option[String]]() { 
    def run = { 
    try { 
     val manager = GSSManager.getInstance 
     val context: GSSContext = manager.createContext(null: GSSCredential) 
     val arrayOfBytes = context.acceptSecContext(serviceTicket, 0, serviceTicket.length) 
     // we ignore arrayOfBytes 
     assert(context.isEstablished, "Failed to establish context: " + context) 
     val username = context.getSrcName.toString 
     Some(username) 
    } catch { 
     case e: Exception => 
     println("failed: " + e.getMessage) 
     None 
    } 
    } 
}) 

krb5.conf.auth 
[libdefaults] 
default_realm = XXX 
allow_weak_crypto=true 
default_tkt_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
default_tgs_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
permitted_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
default_checksum = rsa-md5 
kdc_timesync = 0 
kdc_default_options = 0x40000010 
clockskew = 30000 
check_delegate = 0 
ccache_type = 3 
kdc_timeout = 60000 
forwardable = true 
dns_lookup_realm = true 
dns_lookup_kdc = true 
ticket_lifetime = 24h 

#excluding realms and domain_realm 

jaas.conf.auth (server section) 

Server { 
    com.sun.security.auth.module.Krb5LoginModule required 
    useKeyTab=false 
    debug=true 
    isInitiator=false 
    storeKey=true 
    useTicketCache=false 
    principal="XXX"; 
}; 

Aktualizacja: W przypadku pomaga. Myślę, że klient wysyła bilet SPNEGO, ponieważ jeśli spróbuję zmusić kontekst do zaakceptowania tylko Kerberos (1.2.840.113554.1.2.2) otrzymuję komunikat o błędzie failed: No credential found for: 1.3.6.1.5.5.2 usage: Accept

Aktualizacja 2: To nie jest tak naprawdę odpowiedź , ale jeśli zmienię sposób, w jaki klient systemu Windows tworzy bilet, działa. Jeśli więc zamiast tworzyć bilet zawinięty SPNEGO, utworzysz bilet jedyny Kerberos, zostanie on zaakceptowany przez Javę8. Zatem zmiana "Negocjuj" na "Kerberos" poniżej rozwiązuje problem.

Secur32.INSTANCE.AcquireCredentialsHandle(
     servicePrincipalName, 
     "Negotiate", // Change to "Kerberos" 
     new NativeLong(Sspi.SECPKG_CRED_OUTBOUND), 
     null, 
     authIdentity.getPointer, 
     null, 
     null, 
     phClientCredential, 
     ptsClientExpiry) 
+0

Spróbuj użyć "NTLM" zamiast "Negocjuj" i powiedz mi, czy to działa. Miałem podobny problem. – kukis

+0

Czy java8 może porzucić wsparcie dla 'allow_weak_crypto = true'? –

+0

Java 8 zmieniła domyślną wartość dla allow_weak_crypto na false, więc nie można używać DES, chyba że jest jawnie określone jako prawdziwe: https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8 .html –

Odpowiedz

1

Kerberos/SPNEGO jest domeną odpady ..

Z tego, co przychodzi mi do głowy, poniżej listy kontrolnej z nadzieją, że szybko będzie żadnej pomocy.

  1. Odświeżyłeś swój zestaw klawiszy? z tym samym JDK, którego używasz po stronie serwera?
  2. Czy twój serwer działa pod odpowiednim użytkownikiem (zgodnie z definicją w karcie klucza)?
  3. Czy wygenerowałeś je wybierając opcję "never expire"?
  4. Czy żądasz szyfrowania 256 bitów? Widać wpisując (typ klucza AES-18 = 256):

    % JAVA_HOME% \ bin \ klist -e -a -f -k XX.keytab

    %JAVA_HOME%\bin\klist -e -f -a -k XX.keytab]

    Jeśli tak, dodajesz unrestricted policy filesUS_export_policy.jar w% JAVA_HOME% \ jre \ lib \ security? Upewnij się, że wartość KVNO jest taka sama na liście, jaką otrzymujesz. W idealnej sytuacji powinieneś zobaczyć tylko jedno wyjście.

  5. Czy Twój węzeł SPN można pingować?

  6. Czy lista serwerów KDC jest poprawna?
  7. Zwróć uwagę na plik krb5.conf. Mam problem z. Wydaje się, że rozróżniana jest wielkość liter nawet w środowisku Windows.

Kerberos może być trudny w konfiguracji. Więc powodzenia.