“检测到有缺陷的令牌”使用Kerberos / Spring Security / IE / Active Directory的错误(NTLM不是Kerberos) [英] "Defective token detected" error (NTLM not Kerberos) with Kerberos/Spring Security/IE/Active Directory

查看:140
本文介绍了“检测到有缺陷的令牌”使用Kerberos / Spring Security / IE / Active Directory的错误(NTLM不是Kerberos)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们无法让Spring Security / Kerberos / AD适用于我们的网络应用。我们的诊断是我们的AD服务器发送一个NTLM令牌(我们可以告诉它以TlRMTVNT .....开头)到IE和IE然后将它发送到我们的应用程序并且它失败了。我们的AD服务器应该向IE发送Kerberos / SPNEGO令牌。

We are having trouble getting Spring Security/Kerberos/AD to work for our web app. Our diagnosis is that our AD server sending an NTLM token (we can tell as it starts with "TlRMTVNT.....") to IE and IE is then sending this to our application and it's failing. Our AD server should be sending a Kerberos/SPNEGO token to IE.

移动部件如下:


  • Spring Security 3.0(已打补丁)

  • Microsoft Windows Server Enterprise 2003 SP1 Active Directory

  • IE 8

  • Tomcat(TC Server 6.0)

  • Java 1.6

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

我们已按照此处的说明详细说明了所有内容:

We have set everything up as detailed in the instructions here:

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

这涉及:


  • 创建普通用户作为服务主体(与机器名称相同)我们的应用程序驻留)。我们设置了以下帐户选项:


    • 已禁用'使用必须在下次登录时更改密码'

    • 已启用'密码永不过期'

    • 已启用'使用Kerberos DES ...'

    • 已禁用'不需要Kerberos预身份验证'

    • 注意:Server 2003不显示此帐户支持Kerberos AES 128位...和此帐户支持Kerberos AES 256位...选项

    • Creating a normal user as the Service Principal (the same as the machine name where our application resides). We set the following account options:
      • disabled 'Use has to change password at next logon'
      • enabled 'password never expires'
      • enabled 'Use Kerberos DES…'
      • disabled 'Do not require Kerberos preauthentication'
      • NOTE: Server 2003 does not present the 'This account supports Kerberos AES 128 bit…' and 'This account supports Kerberos AES 256 bit…' options

      • 配置Spring Security(spnego.xml)以使用Kerberos(SpnegoEntryPoint,SpnegoAuthenticationProcessingFilter)和KerberosServiceAuthenticationProvider bean)通过提供我们的服务主页名和keytab文件位置。

      • 配置spnego.xml以读取在WEB-INF / etc中复制的keytab文件。









      当我们启动TC服务器时,我们可以很好地看到事情初始化(即没有错误 - 从keytab获得的原则密钥):

      When we started up our TC server we could see things initializing nicely (i.e. without error - "principles key obtained from the 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/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK
      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/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK to Subject Commit Succeeded 
      
      Finished creating instance of bean 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8' 
      

      Rea为了进行测试,我们在IE中启用了Windows集成身份验证,并确保该域名已在IE的本地Intranet站点部分中列出。然后,我们使用完全限定的域名连接到我们的Web应用程序。

      Ready to test, we then enabled "Windows Integrated Authentication" in IE and made sure that the domain was listed in IE's local intranet site section. We then connected to our web application using the fully qualified domain name.

      当我们这样做时,我们在浏览器中收到以下错误:

      When we did so we got the following errors in the browser:

      500 Internal server error.
      

      和TC Server日志文件中:

      and in the TC Server log file:

      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
      

      似乎(从我们可以看出)AD服务器发送NTLM令牌(我们可以告诉它以TlRMTVNT .....开头)到IE,然后IE将其发送到我们的应用程序并且它失败了。

      It seems (from what we can make out) that the AD server sending an NTLM token (we can tell as it starts with "TlRMTVNT.....") to IE and IE is then sending this to our application and it's failing.

      我们的AD服务器应该向IE发送Kerberos / SPNEGO令牌。

      Our AD server should be sending a Kerberos/SPNEGO token to IE.

      其他说明:


      • 我们的服务器(tc服务器)和客户端(浏览器) 在不同的(虚拟)机器上和同一域中。

      • Our server(tc server) and client(browser) are on different (virtual) machines and in same domain.

      推荐答案

      当您在同一台计算机上运行客户端和服务器时,可能会发生这种情况。当您使用IE与运行tomcat的计算机通信时,请确保这些是不同的计算机。

      This can happen when you are running the client and server on the same machine. When you use IE to talk to the machine running tomcat ensure that these are distinct machines.

      此外,您需要确保服务器计算机已加入到指定的域中。 keytab(testdomain.ourcompany.co.uk)或者你可能会回到NTLM。即使您的服务器位于未加入域的计算机上,您的密钥表仍然可以正常工作(您将看到您显示的好密钥表解密),但IE可能会感到困惑,而不是做正确的事情。

      Additionally you need to ensure that the server machine is joined to the domain specified in the keytab (testdomain.ourcompany.co.uk) or you might drop back to NTLM. Your keytab can still work even if your server is on a machine not joined to the domain (you'll see the nice keytab decrypt that you showed), but IE can get confused and not do the correct thing.

      AD只是非常喜欢为Server 2003说arcfour-hmac,所以你需要确保在krb5.ini文件中正确设置它。

      AD only really likes to speak arcfour-hmac for Server 2003 so you need to ensure that you set this up correctly in your krb5.ini file.

      您可以像这样正确创建密钥表:

      You can correctly create the keytab like this:

      C:\>ktpass -princ HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK -mapuser ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK -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/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK to ourweb.testdomain.ourcompany.co.uk.
      Key created.
      Output keytab to ourweb.keytab:
      Keytab version: 0x502
      keysize 75 HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK ptype 1 (KRB5_NT_PRINCIPAL)
      vno 3 etype 0x17 (RC4-HMAC) keylength 16 (0x0fd0e500225c4fca9a63a9998b17ca32)
      

      我没看到你已经设置了krb5.ini文件。您需要在服务器计算机上正确设置该设置(默认位置C:\ WINDOWS \ krb5.ini):

      I did not see that you had set up a krb5.ini file. You will need to have that set correctly on your server machine (default location 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
      }
      

      您可能还需要设置以下属性(如果您尝试从IDE运行此属性):

      You might also need to set the following properties (if you are trying to run this from an 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>
      

      我正在使用maven的org.codehaus.mojo插件,它在pom文件中设置这些:

      I was using the org.codehaus.mojo plugin for maven which sets these in the pom file like this:

      <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>
      

      这篇关于“检测到有缺陷的令牌”使用Kerberos / Spring Security / IE / Active Directory的错误(NTLM不是Kerberos)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆