mvc dependencia java spring-security kerberos

java - dependencia - Error "Se detectó un token defectuoso"(NTLM no Kerberos) con Kerberos/Spring Security/IE/Active Directory



spring security module (3)

Esto puede suceder cuando está ejecutando el cliente y el servidor en la misma máquina. Cuando utilice IE para hablar con la máquina que ejecuta Tomcat, asegúrese de que se trata de máquinas distintas.

Además, debe asegurarse de que la máquina del servidor esté unida al dominio especificado en el keytab (testdomain.ourcompany.co.uk) o puede regresar a NTLM. Su keytab puede seguir funcionando incluso si su servidor está en una máquina que no está unida al dominio (verá el buen descifrado de keytab que mostró), pero IE puede confundirse y no hacer lo correcto.

A AD solo le gusta hablar arcfour-hmac para Server 2003, por lo que debe asegurarse de que configura esto correctamente en su archivo krb5.ini.

Puede crear correctamente el keytab así:

C:/>ktpass -princ HTTP/[email protected] -mapuser [email protected] -crypto RC4-HMAC-NT -ptype K RB5_NT_PRINCIPAL -pass * -out ourweb.keytab Targeting domain controller: test-dc.ourcompany.co.uk Using legacy password setting method Successfully mapped HTTP/[email protected] to ourweb.testdomain.ourcompany.co.uk. Key created. Output keytab to ourweb.keytab: Keytab version: 0x502 keysize 75 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x17 (RC4-HMAC) keylength 16 (0x0fd0e500225c4fca9a63a9998b17ca32)

No vi que habías configurado un archivo krb5.ini. Necesitará tener ese conjunto correctamente en su máquina servidor (ubicación predeterminada C: / WINDOWS / krb5.ini):

[domain_realm] .testdomain.ourcompany.co.uk = TESTDOMAIN.OURCOMPANY.CO.UK testdomain.ourcompany.co.uk = TESTDOMAIN.OURCOMPANY.CO.UK [libdefaults] default_realm = TESTDOMAIN.OURCOMPANY.CO.UK permitted_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 default_tgs_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 default_tkt_enctypes = aes128-cts aes256-cts arcfour-hmac-md5 [realms] VERDAD.LOCAL = { kdc = test-dc.ourcompany.co.uk admin_server = test-dc.ourcompany.co.uk default_domain = TESTDOMAIN.OURCOMPANY.CO.UK }

Es posible que también deba establecer las siguientes propiedades (si está intentando ejecutar esto desde un IDE):

<systemProperties> <java.security.krb5.kdc>test-dc.ourcompany.co.uk</java.security.krb5.kdc> <java.security.krb5.realm>TESTDOMAIN.OURCOMPANY.CO.UK</java.security.krb5.realm> </systemProperties>

Estaba usando el plugin org.codehaus.mojo para maven que establece esto en el archivo pom como este:

<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>tomcat-maven-plugin</artifactId> <configuration> <server>tomcat-development-server</server> <port>8080</port> <path>/SecurityTest</path> <systemProperties> <java.security.krb5.kdc>test-dc.ourcompany.co.uk</java.security.krb5.kdc <java.security.krb5.realm>TESTDOMAIN.OURCOMPANY.CO.UK</java.security.krb5.realm> </systemProperties> </configuration> </plugin> </plugins> </build>

Estamos teniendo problemas para que Spring Security / Kerberos / AD funcione para nuestra aplicación web. Nuestro diagnóstico es que nuestro servidor de AD que envía un token NTLM (podemos decir que comienza con "TlRMTVNT .....") a IE y luego IE lo está enviando a nuestra aplicación y está fallando. Nuestro servidor de AD debe enviar un token de Kerberos / SPNEGO a IE.

Las "partes móviles" son las siguientes:

  • Spring Security 3.0 (parcheado)
  • Microsoft Windows Server Enterprise 2003 SP1 Active Directory
  • IE 8
  • Tomcat (TC Server 6.0)
  • Java 1.6

Hemos configurado todo como se detalla en las instrucciones aquí:

https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension

Esto implicaba:

  • Creación de un usuario normal como el Principal del Servicio (igual que el nombre de la máquina donde reside nuestra aplicación). Establecemos las siguientes opciones de cuenta:
    • deshabilitado ''El uso tiene que cambiar la contraseña en el próximo inicio de sesión''
    • habilitado ''la contraseña nunca caduca''
    • habilitado ''Usar Kerberos DES ...''
    • deshabilitado ''No requiere autenticación previa Kerberos''
    • NOTA: Server 2003 no presenta las opciones "Esta cuenta admite Kerberos AES de 128 bits ..." y "Esta cuenta admite Kerberos AES de 256 bits ..."
  • Usó "ktpass.exe" para asignar el nombre principal del servicio (SPN) a este nuevo usuario y exportar esta clave de usuario a un archivo keytab. utilizando ''ktpass / out ourweb.keytab / mapuser [email protected] / princ HTTP/[email protected] / pass * ''
  • Código fuente descargado de https://src.springframework.org/svn/se-security/trunk .
  • Copió el archivo keytab del servidor AD a WEB-INF / etc del código fuente (aplicación).
  • Se realizó un cambio en el archivo SunJaasKerbersoTicketValidator.java para leer el archivo keytab. (Para resolver el error en el que la aplicación no puede leer el archivo keytab de la ruta de clase de Java) options.put ("keyTab", "C: / se-security / spring-security-kerberos / spring-security-kerberos-sample / src / main / webapp / WEB-INF / etc / ourweb.keytab ");
  • Configuró web.xml para usar spnego.xml. contextConfigLocation /WEB-INF/spnego.xml
    • Configuró Spring Security (spnego.xml) para usar Kerberos (SpnegoEntryPoint, SpnegoAuthenticationProcessingFilter y KerberosServiceAuthenticationProvider beans) proporcionando nuestro servicio prinicipal nombre y ubicación de archivo keytab.
    • Configuró spnego.xml para leer el archivo keytab copiado en WEB-INF / etc.

Cuando iniciamos nuestro servidor TC, pudimos ver las cosas inicializando muy bien (es decir, sin error - "clave de principios obtenida de la tabla de teclas"):

Creating instance of bean ''org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8'' Invoking afterPropertiesSet() on bean with name ''org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8'' Config name: C:/WINDOWS/krb5.ini Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is C:/se-security/spring-security-kerberos/spring-security-kerberos-sample/src/main/webapp/WEB-INF/etc/ourwebapp4.keytab refreshKrb5Config is false principal is HTTP/ourwebappweb4.testdomain.ourcompany.co.uk tryFirstPass is false useFirstPass is false storePass is false clearPass is false >>> KeyTabInputStream, readName(): TESTDOMAIN.OURCOMPANY.CO.UK >>> KeyTabInputStream, readName(): HTTP >>> KeyTabInputStream, readName(): ourweb >>> KeyTab: load() entry length: 78; type: 1 >>> KeyTabInputStream, readName(): TESTDOMAIN.OURCOMPANY.CO.UK >>> KeyTabInputStream, readName(): HTTP >>> KeyTabInputStream, readName(): ourweb.testdomain.ourcompany.co.uk >>> KeyTab: load() entry length: 113; type: 1 Added key: 1version: 2 Ordering keys wrt default_tkt_enctypes list default etypes for default_tkt_enctypes: 1. 0: EncryptionKey: keyType=1 kvno=2 keyValue (hex dump)= 0000: 91 01 43 E3 02 A8 B9 83   principal''s key obtained from the keytab principal is HTTP/[email protected] EncryptionKey: keyType=1 keyBytes (hex dump)=0000: 91 01 43 E3 02 A8 B9 83   Added server''s keyKerberos Principal HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UKKey Version 2key EncryptionKey: keyType=1 keyBytes (hex dump)= 0000: 91 01 43 E3 02 A8 B9 83   [Krb5LoginModule] added Krb5Principal  HTTP/[email protected] to Subject Commit Succeeded Finished creating instance of bean ''org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8''

Listo para probar, luego habilitamos "Autenticación integrada de Windows" en IE y nos aseguramos de que el dominio se incluyera en la sección del sitio de intranet local de IE. Luego nos conectamos a nuestra aplicación web utilizando el nombre de dominio completo.

Cuando lo hicimos conseguimos los siguientes errores en el navegador:

500 Internal server error.

y en el archivo de registro del servidor TC:

Negotiate Header was invalid: Negotiate TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw== org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesfull at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:74) at org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:92) at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:120) at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48) at org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:132) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at com.springsource.metrics.collection.web.HttpRequestMetricCollectionValve.invoke(HttpRequestMetricCollectionValve.java:44) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:379) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619) Caused by: java.security.PrivilegedActionException: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:396) at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:72) ... 25 more Caused by: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag) at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:80) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:287) at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267) at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:161) at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:1) ... 28 more SecurityContextHolder now cleared, as request processing completed

Parece (de lo que podemos entender) que el servidor de AD que envía un token NTLM (podemos decir que comienza con "TlRMTVNT .....") a IE y luego IE lo está enviando a nuestra aplicación y está fallando.

Nuestro servidor de AD debe enviar un token de Kerberos / SPNEGO a IE.

Otras notas:

  • Nuestro servidor (servidor tc) y cliente (navegador) están en diferentes máquinas (virtuales) y en el mismo dominio.

También me encontré con este problema. Para aquellas personas desafortunadas que tendrán este problema en el futuro, otra causa de este problema es acceder al servidor por IP en lugar de a un registro A (nombre de host)


También tuve el mismo problema y me llevó mucho tiempo encontrar al culpable. Entonces, si has hecho todo lo anterior y aún usa el token NTLM en lugar de kerberos. Asegúrate de no tener SPN duplicado. en mi caso tuve 2 cuentas asignadas al mismo SPN y la razón fue que anteriormente ejecuté una aplicación web separada en el mismo servidor que usaba una cuenta de servicio diferente pero asignada al mismo SPN que era HTTP /

Espero eso ayude