提问者:小点点

“检测到 GSSException 有缺陷的令牌” - 尝试使用 Kerberos 对在 Windows 上运行的 Tomcat 进行身份验证时


在Windows 2012上运行时,我正在努力对Java的Web容器进行身份验证(我尝试过Tomcat和Jetty)。

每次尝试Negotiate auth方案时,我都会收到一个错误:<code>org.ietf.jgss。GSSException:检测到有缺陷的标记(机制级别:GSSHeader未找到正确的标记)

重现步骤

首先设置Windows Server 2012或2016实例并安装active directory域服务。

在我的示例中,我创建了:

>

  • NETBIOS域名:NICKIS

    域名:nickis.life

    在Active Directory上创建kerberos主体用户

    重要:确保名字、姓氏和全名相同!

    在我的例子中,新用户是:

    DN=CN=kerberos500,CN=Users,DC=nickis,DC=life

    登录域= < code > Kerberos 500 @ nick is . life

    NETBIOS\samAccountName = NICKIS\kerberos500

    从Windows Active Directory Server运行setspn命令

    setspn -A HTTP/nickis.life@NICKIS.LIFE kerberos500
    

    示例输出:

    C:\Users\Administrator>setspn -A HTTP/nickis.life kerberos500
    Checking domain DC=nickis,DC=life 
    Registering ServicePrincipalNames for CN=kerberos500,CN=Users,DC=nickis,DC=life
            HTTP/kerberos500.nickis.life
    Updated object
    

    从Windows Active Directory服务器运行ktpass命令

    ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass XXXXpasswordforkerberos500userXXXX -crypto DES-CBC-MD5 -pType KRB5_NT_PRINCIPAL +DesOnly
    

    示例输出:

    C:\Users\Administrator>ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass xxxxxxxx -crypto DES-CBC-MD5 -pType KRB5_NT_PRINCIPAL +DesOnly
    Targeting domain controller: WIN-OVV6VHBGIB8.nickis.life
    Using legacy password setting method
    Successfully mapped HTTP/kerberos500.nickis.life to kerberos500.
    Key created.
    Output keytab to c:\Users\Administrator\kerberos500.keytab:
    Keytab version: 0x502
    keysize 71 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x3 (DES-CBC-MD5) keylength 8 (0xcd07200bea625d20)
    Account kerberos500 has been set for DES-only encryption.
    

    此时,您将拥有一个keytab文件:

    c:\Users\Administrator\kerberos500.keytab
    

    用户主体:

    HTTP/kerberos500.nickis.life@NICKIS.LIFE
    

    这是需要提供给GSSApi以使用Kerberos进行单点登录的两个输入。

    因此,我将这些输入部署到Hadoop安全模块中web容器的kerberos安全领域。

    卷曲测试我尝试使用卷曲来测试它,但没有成功:

    curl --negotiate -u : http://nickis.life:8080/my/webapp

    Internet Explorer测试我也尝试使用Internet Explorer。我将< code>nickis.life域添加到了Internet Explorer的可信角色中。然后我在internet explorer中启动这个网站:http://nickis.life:8080

    无论哪种方式,我都会得到下面的错误:

    org.apache.hadoop.security.authentication.client.AuthenticationException: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
        at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.authenticate(KerberosAuthenticationHandler.java:398) ~[hadoop-auth-2.7.1.jar:?]
    
    ...
    
    Caused by: org.ietf.jgss.GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
        at sun.security.jgss.GSSHeader.<init>(Unknown Source) ~[?:1.8.0_131]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) ~[?:1.8.0_131]
        at sun.security.jgss.GSSContextImpl.acceptSecContext(Unknown Source) ~[?:1.8.0_131]
        at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler$2.run(KerberosAuthenticationHandler.java:365) ~[hadoop-auth-2.7.1.jar:?]
        at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler$2.run(KerberosAuthenticationHandler.java:347) ~[hadoop-auth-2.7.1.jar:?]
        at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_131]
        at javax.security.auth.Subject.doAs(Unknown Source) ~[?:1.8.0_131]
        at org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler.authenticate(KerberosAuthenticationHandler.java:347) ~[hadoop-auth-2.7.1.jar:?]
    

    我被难住了。注意:我在这里和那里找到了几个链接,但没有一个像我在这里总结的那样在遵循的步骤中是完全包含的,并且其中提供的解决方案都不适合我。

    • 我正在尝试从域上与服务器运行的不同机器登录kerberos
    • 我已经尝试了各种组合的键选项卡生成变化都没有工作。
    • 没有重复的SPN。
    • 我尝试将域服务器中的DNS设置为A记录。
    • 我想知道是否有一些kerberos windows服务器设置步骤,并且Microsoft员工验证了这里不应该是这种情况:https://social.msdn.microsoft.com/Forums/sharepoint/en-US/db15ad96-e269-436e-952f-fe9dfb39da8a/setting-up-a-test-windows-server-active-directory-for-kerberos-testing?forum=winserverDS

    有人能追踪到我搞砸了什么吗?

    更新:

    • 我有域设置为 fusionis.life 的 AD 服务器,并且 AD 服务器 WIN-OVV6VHBGIB8.fusionis.life
    • 我将 tomcat 服务器移动到域中的另一台 Windows 计算机。DESKTOP-VTPBE99.fusionis.life
    • 我打开dnsmgmt.msc并添加了一个带有“kerberos500.nickis.life”的“正向查找区域”,并将主机设置为 DESKTOP-VTPBE99.fusionis.life 框的IP。
    • 我删除了AD帐户,重新创建了它,然后按照票证上的一个答案中的建议再次重新生成了密钥表。

    C:\Users\Administrator

    >

  • 我在服务器上保存了keytab更新文件,然后将服务主体更新为HTTP/kerberos500.nickis.life@NICKIS.LIFE

    我以域用户身份登录tomcat计算机,并补充道http://kerberos500.nickis.life到受信任的站点,然后导航到http://kerberos500.nickis.life:8764

    我检查了Kerberos 500 AD“account”选项卡中所有加密复选框的组合。

    现在我有一个新的错误…

    < code>GSSException:未提供有效的凭据(机制级别:找不到任何Kerberos凭据)

    更新:

    终于解决了。我得到了最后一个错误,因为我需要 fusionis.lifenickis.life 位于同一主机上


  • 共3个答案

    匿名用户

    错误“检测到有缺陷的令牌”可能意味着检测到ntlm令牌。这就是协商

    1. HTTP服务的spn与浏览器输入的URL不匹配。它们需要匹配,否则Kerberos将失败。要工作,浏览器应使用:http://kerberos500.nickis.life:8080不http://nickis.life:8080.我这样说是基于我在keytab创建语法中看到的内容。在这里,您将SPN编码为:HTTP/kerberos500.nickis.life@NICKIS.LIFE.这就是为什么你需要使用http://kerberos500.nickis.life:8080.当您要求浏览器访问时,浏览器将不知道如何访问您的web服务http://nickis.life:8080.使用该顶部URL,浏览器假定需要查找在Active Directory域控制器上运行的web服务(任何只有昵称.life的服务都假定在域控制器上)。出于安全原因,DC不应运行web服务器
    2. 您需要添加http://kerberos500.nickis.life作为IE设置下的受信任站点。或者,*.nickis。生活也会起作用。(您将其称为“受信任的角色”,而实际上称为“可信的站点”)
    3. 您将Kerberos加密类型限制为DES-CBC-MD5。从Windows Server 2008 Active Directory R2开始,默认情况下禁用DES。DES现在是一种过时且通常不安全的加密类型。使用AES128要好得多,甚至更好,AES256。您可以按照下面的示例重新生成keytab来解决这个问题
    4. 在AD用户帐户kerberos500中,转到“帐户”选项卡,滚动到底部,选中DES、AES 128和AES 256的所有框,然后确定您将退出对话框。您必须选中这些复选框,即使您完成了上面的所有操作,否则Kerberos身份验证仍将失败

    如何正确地重新生成keytab:当您计划将keytab与AD用户帐户相关联时,您不应该运行setspn -a命令来向该用户添加spn。

    setspn -D HTTP/nickis.life@NICKIS.LIFE kerberos500
    

    然后重新生成keytab,我唯一的改变是我告诉它使用所有的加密类型。在认证过程中,客户端和服务器将商定最强的公共密钥。

    ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass XXXXpasswordforkerberos500userXXXX -crypto ALL -pType KRB5_NT_PRINCIPAL
    


    然后将旧密钥表替换为新密钥表。有关密钥表的其他深入信息,可以从我的技术文章中阅读有关如何创建 Kerberos 密钥表的更多信息:Kerberos 密钥表 – 解释。我经常根据我在这个论坛上看到的问题回去编辑它。

    顺便说一句,HTTP/kerberos500.nickis。生活是服务主体,而不是你在问题中所写的用户主体。我只使用web浏览器来测试HTTP场景中的Kerberos,而不使用cURL。

    我很肯定,如果你勤奋地完成我上面强调的所有四点,你会解决这个问题。

    EDIT1:这个答案假设你有一个HTTP服务在一个完全限定域名为kerberos500.nickis.life.的主机上运行。如果你没有这样一个名字为kerberos500.nickis.life.的主机,我的答案会稍微改变。如果有的话,请告诉我。

    EDIT2:要实现使用 http://nickis.life:8080 URL 进行身份验证的目标,您可以继续使用已创建的相同密钥表。

    在 AD 帐户 NICKIS\kerberos500 上,转到“帐户”选项卡,滚动到底部,然后选中“为此帐户使用 Kerberos DES 加密类型”框。

    然后通过组策略在AD域级别启用DES加密本身。为此,请执行以下操作:

    1. 打开组策略管理控制台(GPMC)。
    2. 编辑默认域策略GPO。(创建一个新的域级GPO并对其进行编辑更安全,但这取决于您)。
    3. 导航到计算机配置

    参考:Kerberos支持的加密类型的Windows配置

    编辑 3:避免在同一台计算机上运行 Kerberos KDC(DC)、客户端和服务器。这是获得“有缺陷的令牌错误”的经典秘诀,即使您已经正确完成了其他所有操作。

    编辑4:(OP验证的最终更新):查看了新的ktpass keytab创建输出,我看到了:目标域控制器:WIN-OVV6VHBGIB8.fusionis.life。现在,keytab中定义的SPN是HTTP/kerberos500.nickis.life。AD域名与您定义的SPN不同,因此,除非在这些域之间设置某种信任,否则这将无法正常工作。如果您没有信任,则需要使用HTTP/kerberos500.fusionis的SPN。生活。

    匿名用户

    对我来说,问题是配置的SPN与指定的url不同。

    因此,假设SPN是HTTP / serviceX.domain.com,当访问服务时,应通过 http://serviceX.doamin.com 访问它,否则,它将引发有缺陷的令牌错误。

    (我还发现所有与Keberos相关的错误消息都很令人困惑,也许MIT故意让它难以理解,相应地更难破解。)

    匿名用户

    试试这个:

    解决方案1

    在windows cmd上运行此命令:

    ksetup /addkdc ksetup /addhosttorealmmap

    并在浏览器上设置SPNEGO设置

    解决方案2

    尝试使用Firefox,之前这样做:

    1)在Firefox中打开此URL

    关于:配置

    2)设置以下内容:network . negotiate-auth . trusted-uri

    为任何需要协商身份验证的群集DNS域设置(例如启用kerberos的群集HTTP身份验证)。

    例子:

    network . negotiate-auth . trusted-URIs = . lily . cloud era . com,. solr.cloudera.com

    2) 设置此项:network.auth。使用sspi=false 3)重新启动Firefox 4)您必须从这里下载Windows安装程序:

    http://web.mit.edu/kerberos/dist/#kfw-4.0

    5) 将 Kerberos 客户端配置复制到此处

    c:\ program data \ MIT \ Kerberos 5 \ krb5 . ini

    6)使用MIT kerberos GUI客户端创建票证

    7) 使用火狐浏览器重试

    希望它能有所帮助。