Nous avons du mal à faire fonctionner Spring Security/Kerberos/AD pour notre application Web. Notre diagnostic est que notre serveur AD envoie un token NTLM (on peut dire comme il commence par "TlRMTVNT .....") à IE et IE envoie alors ceci à notre application et il échoue. Notre serveur AD devrait envoyer un jeton Kerberos/SPNEGO à IE.
Les "pièces mobiles" sont les suivantes:
Nous avons tout configuré comme détaillé dans les instructions ici:
https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension
Cela impliquait:
Lorsque nous avons démarré notre serveur TC, nous pouvions voir les choses s’initialiser correctement (c’est-à-dire sans erreur - "principes clés obtenus à partir du keytab"):
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'
Prêt à tester, nous avons ensuite activé "l'authentification intégrée Windows" dans IE et nous nous sommes assurés que le domaine était répertorié dans la section du site intranet local d'IE. Nous nous sommes ensuite connectés à notre application Web à l'aide du domaine pleinement qualifié. Nom.
Lorsque nous l'avons fait, nous avons eu les erreurs suivantes dans le navigateur:
500 Internal server error.
et dans le fichier journal du serveur 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
Il semble (d'après ce que nous pouvons comprendre) que le serveur AD envoie un jeton NTLM (nous pouvons dire qu'il commence par "TlRMTVNT .....") à IE et IE envoie alors ceci à notre application et il échoue.
Notre serveur AD devrait envoyer un jeton Kerberos/SPNEGO à IE.
Autres notes:
Cela peut se produire lorsque vous exécutez le client et le serveur sur la même machine. Lorsque vous utilisez IE pour parler à la machine exécutant Tomcat, assurez-vous qu'il s'agit de machines distinctes.
De plus, vous devez vous assurer que la machine serveur est jointe au domaine spécifié dans le keytab (testdomain.ourcompany.co.uk) ou vous pouvez revenir à NTLM. Votre keytab peut toujours fonctionner même si votre serveur est sur une machine non jointe au domaine (vous verrez le keytab de Nice décrypter que vous avez montré), mais IE peut être confus et ne pas faire le chose correcte.
AD n'aime vraiment parler arcfour-hmac que pour Server 2003, vous devez donc vous assurer que vous l'avez configuré correctement dans votre fichier krb5.ini.
Vous pouvez créer correctement le keytab comme ceci:
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)
Je n'ai pas vu que vous aviez créé un fichier krb5.ini. Vous devrez l'avoir défini correctement sur votre machine serveur (emplacement par défaut 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
}
Vous devrez peut-être également définir les propriétés suivantes (si vous essayez de l'exécuter à partir d'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>
J'utilisais le plugin org.codehaus.mojo pour maven qui les définit dans le fichier pom comme ceci:
<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>
J'ai également rencontré ce problème. Pour les personnes malchanceuses qui auront ce problème à l'avenir, une autre cause de ce problème est d'accéder au serveur par ip au lieu de son enregistrement A (nom d'hôte)
J'ai également eu le même problème et il m'a fallu très très longtemps pour trouver le coupable. Donc, si vous avez fait tout ce qui précède et qu'il utilise toujours un jeton NTLM au lieu de kerberos. assurez-vous que vous n'avez pas de SPN en double. dans mon cas, j'avais 2 comptes mappés sur le même SPN et la raison était que j'avais précédemment exécuté une application Web distincte sur le même serveur qui utilisait un compte de service différent mais mappé au même SPN qui était HTTP /
J'espère que ça aide