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

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

问题描述

我们无法让 Spring Security/Kerberos/AD 为我们的 Web 应用程序工作.我们的诊断是我们的 AD 服务器向 IE 发送了一个 NTLM 令牌(我们可以看出它以TlRMTVNT ....."开头),然后 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 活动目录
  • IE 8
  • Tomcat(TC 服务器 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 位..."选项
    • 通过提供我们的服务主体名称和密钥表文件位置,配置 Spring Security (spnego.xml) 以使用 Kerberos(SpnegoEntryPoint、SpnegoAuthenticationProcessingFilter 和 KerberosServiceAuthenticationProvider bean).
    • 配置 spnego.xml 以读取复制到 WEB-INF/etc 中的密钥表文件.

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

    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:WINDOWSkrb5.ini
    Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is C:se-securityspring-security-kerberosspring-security-kerberos-samplesrcmainwebappWEB-INFetcourwebapp4.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' 
    

    准备测试,然后我们在 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 服务器日志文件中:

    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 服务器向 IE 发送了一个 NTLM 令牌(我们可以看出它以TlRMTVNT ....."开头),然后 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.

    此外,您需要确保服务器计算机已加入密钥表 (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:WINDOWSkrb5.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:WINDOWSkrb5.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>
    

    我使用 org.codehaus.mojo 插件为 maven 将这些设置在 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>
    

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

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