java - “GSSException Defective token detected”-尝试使用Kerberos对Windows上运行的Tomcat进行身份验证时

标签 java windows active-directory kerberos gssapi

在Windows 2012上运行时,我难以通过Java网络容器进行身份验证(我已经尝试过Tomcat和Jetty)。

每次尝试协商身份验证方案时,我都会收到一个错误:org.ietf.jgss.GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
重现的步骤

首先设置Windows Server 2012或2016实例,然后安装Active Directory域服务。

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

  • NETBIOS域: NICKIS
  • Dns域: nickis.life

  • 在Active Directory上创建kerberos主题用户

    重要提示:请确保名字,姓氏和名字相同!

    我的新用户是:

    DN = CN=kerberos500,CN=Users,DC=nickis,DC=life
    登录名+域 = kerberos500@nickis.life
    NETBIOS\samAccountName = NICKIS\kerberos500
    从Windows Active Directory服务器运行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.
    

    现在,您将拥有一个 key 表文件:
    c:\Users\Administrator\kerberos500.keytab
    

    和一个用户主体:
    HTTP/kerberos500.nickis.life@NICKIS.LIFE
    

    这是提供给GSSApi以获得Kerberos单点登录所需的2个输入。

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

    卷发测试我尝试使用curl进行测试失败:
    curl --negotiate -u : http://nickis.life:8080/my/webapp
    Internet Explorer测试我也尝试使用Internet Explorer。我将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登录
  • 我尝试了各种不同的keytab生成变体组合,但均无效。
  • 没有重复的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,并添加了一个“Forward Lookup Zone”和“kerberos500.nickis.life”,并将HOST设置为DESKTOP-VTPBE99.fusionis.life框的IP。
  • 我删除了AD帐户,重新创建了该帐户,然后按照票证上的答案之一中的建议再次重新生成了 key 表。
  • C:\Users\Administrator>ktpass -out c:\Users\Administrator\kerberos500.keytab -princ HTTP/kerberos500.nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass xxxxxxxxx -crypto ALL -pType KRB5_NT_PRINCIPAL Targeting domain controller: WIN-OVV6VHBGIB8.fusionis.life Using legacy password setting method Successfully mapped HTTP/kerberos500.nickis.life to kerberos500. Key created. Key created. Key created. Key created. Key created. Output keytab to c:\Users\Administrator\kerberos500.keytab: Keytab version: 0x502 keysize 67 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x1 (DES-CBC-CRC) keylength 8 (0x04e30b9183ba8389) keysize 67 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x3 (DES-CBC-MD5) keylength 8 (0x04e30b9183ba8389) keysize 75 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x17 (RC4-HMAC) keylength 16 (0xe39a141de38abd8750bf9c0bf49fd1c5) keysize 91 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x12 (AES256-SHA1) keylength 32 (0xe368a1b060cfe4816f522c1c5f62ca07fe201ed96c6d018054dfbd5b86251892) keysize 75 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x11 (AES128-SHA1) keylength 16 (0x1b1a548fa2893a78c6f4c7f9c482b614)
  • 我将 key 表更新文件保存在服务器上,然后将服务主体更新为HTTP/kerberos500.nickis.life@NICKIS.LIFE
  • 我以域用户身份登录tomcat机器,将http://kerberos500.nickis.life添加到受信任的站点,然后导航到http://kerberos500.nickis.life:8764
  • 我在kerberos500 AD“帐户”选项卡中选中了加密复选框的所有组合。

  • 现在我遇到了一个新的错误...
    GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos credentails)
    更新:

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

    最佳答案

    错误“检测到有缺陷的 token ”很可能意味着检测到 token 。这就是失败时在流行的Web浏览器中使用的协商机制-否则Web服务器未指示该机制。在操作系统上,其上的IE Web浏览器(和Firefox,如果配置正确)基本上会说,如果您不使用Kerberos,我将向您发送NTLM token 。服务器回复“没有办法”,我什至都不知道NTLM,所以我称您发送给我的内容有缺陷。由于您似乎是第一次进行此设置,因此当Kerberos失败时,您可能未配置任何后备机制(例如NTLM),因此该错误消息。我们通过理解Kerberos为什么会失败来解决此问题。我想我在两个地方看到了您的问题失败的原因,这与SPN和受信任的站点有关。即使您解决了这两项,也存在与加密有关的第三个原因和第四个原因,为什么它可能继续失败。

  • HTTP服务的与浏览器输入的URL不匹配。这些需要匹配,否则Kerberos将失败。要正常工作,浏览器应使用:http://kerberos500.nickis.life:8080,而不是http://nickis.life:8080。我说这是基于您在创建语法中看到的。在此过程中,您已经对SPN进行了如下编码:HTTP/kerberos500.nickis.life@NICKIS.LIFE。因此,您需要使用http://kerberos500.nickis.life:8080。当您告诉浏览器转到http://nickis.life:8080时,浏览器将不知道如何使用它。使用该顶级URL,浏览器将假定它需要找到在Active Directory 上运行的Web服务(假定只有nickis.life的任何服务都在域 Controller 上运行)。出于安全考虑,DC永远不要运行Web服务器。
  • 您需要在IE设置下将http://kerberos500.nickis.life添加为“受信任的站点”。另外,*。nickis.life也可以。 (实际上称为“受信任的站点”,您称之为“受信任的角色”)。
  • 您将Kerberos加密类型限制为DES-CBC-MD5。从Windows Server 2008 Active Directory R2开始,默认情况下禁用DES。如今,DES是一种过时且通常不安全的加密类型。使用AES128更好,甚至使用AES256更好。您可以通过以下示例重新生成 key 表来解决此问题。
  • 在AD用户帐户kerberos500中,转到“帐户”选项卡,滚动到底部,然后选中DES,AES 128和AES 256的所有复选框,然后确定您离开了对话框。即使您已完成上述所有操作,也必须选中这些框,否则Kerberos身份验证仍将失败。

  • 如何正确重新生成 key 表:每当您计划制作与该用户帐户关联的 key 表时,都不应运行setspn -a命令将SPN添加到AD用户。原因是因为keytab创建命令将SPN作为命令的一部分添加到了用户帐户中。如果按照我的上述建议后您的方案仍然无法使用,则需要通过setpn -D删除SPN,如下所示:
    setspn -D HTTP/nickis.life@NICKIS.LIFE kerberos500
    

    然后重新生成 key 表,我唯一的变化是我告诉它使用所有加密类型。客户端和服务器将在身份验证过程中就最强的通用协议(protocol)达成一致。
    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
    

    然后,将旧的 key 表替换为新的 key 表。有关 key 表的其他深入信息,您可以从我的技术文章中阅读更多有关如何创建Kerberos key 表的信息:Kerberos Keytabs – Explained。我经常根据在此论坛上看到的问题返回并对其进行编辑。

    顺便说一句,HTTP/kerberos500.nickis.life是服务主体,而不是您在问题中所写的用户主体。我仅使用网络浏览器在此类HTTP场景中测试Kerberos,而不使用cURL。

    如果您认真地完成了以上四点,我很肯定,您将解决此问题。

    编辑1:此答案假定您在具有完全限定域名kerberos500.nickis.life的主机上运行HTTP服务。如果您没有使用该名称的主机,我的回答将略有变化。请让我知道。

    编辑2:要使用http://nickis.life:8080的URL达到身份验证的目的,则可以继续使用已经创建的相同 key 表。

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

    然后,通过组策略在AD域级别上启用DES加密本身。为此,请执行以下操作:
  • 打开组策略管理控制台(GPMC)。
  • 编辑默认域策略GPO。 (创建新的域级GPO并进行编辑比较安全,但这取决于您)。
  • 导航到“计算机配置”>“策略”>“Windows设置”>“安全性设置”>“本地策略”>“安全选项”>“网络安全性:配置Kerberos允许的加密类型”,并选中DES_CBC_MD5和DES_CBC_MD5的两个复选框。重要说明:在同一组策略中,还要确保还选中了RC4,AES128和AES256的复选框。这些加密类型不会用于您的网站票证,但会用于域中的其他所有票证。单击确定,然后退出对话框并关闭GPMC。
  • 在DC服务器和客户端上都运行“gpupdate/force”命令。
  • 在客户端上运行“klist清除”以清除所有Kerberos票证。
  • 在Web浏览器中,清除缓存并删除所有cookie。
  • 确保DC服务器允许端口8080 TCP入站。
  • 再试一次。

  • 引用:Windows Configurations for Kerberos Supported Encryption Type

    编辑3:避免在same机器上运行Kerberos KDC(DC),客户端和服务器。这是获得“缺陷 token 错误”的经典方法,即使您已正确完成所有其他操作。

    编辑4 :(经OP验证的最终更新):查看了新的ktpass keytab创建输出,并且我看到了:定向域 Controller :WIN-OVV6VHBGIB8.fusionis.life。现在, key 表中定义的SPN是HTTP/kerberos500.nickis.life。 AD域名不同于您定义的SPN,因此,除非您在这些域之间建立了某种信任关系,否则它将无法正常工作。如果没有信任关系,则需要使用HTTP/kerberos500.fusionis.life的SPN。

    关于java - “GSSException Defective token detected”-尝试使用Kerberos对Windows上运行的Tomcat进行身份验证时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47227276/

    相关文章:

    java - Tomcat 返回带有一字节响应的 HTTP 500

    java - 将 XML 解码为 Java 对象

    java - 获取异常 OutofMemoryError

    windows - 无法从 IE 中找到凭据导致 HDFS WebUI Kerberos 身份验证失败

    asp.net - 如何使用动态数据和 Active Directory 实现基于角色的安全性?

    asp-classic - 在经典 ASP 中更改事件目录密码

    Java 调用 C 调用 Java

    linux - Gradles 的 zipTree 在 Unix 和 Windows 上的不同行为?

    windows - 如何批量命名根据某些表达式命名的文件夹

    active-directory - 如何使用 XPages 查询 AD?