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

在Windows 2012上运行时,我正在努力向Java Web容器进行身份验证(我尝试过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 Domain:尼基斯

  • 域名:nickis.life

在 Active Directory 上创建 kerberos 主题用户

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

在我的情况下,新用户是:

断续器 = CN=kerberos500,CN=Users,DC=nickis,DC=life

登录+域名 = kerberos500@nickis.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 Server 运行 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.

此时,您现在将拥有一个密钥表文件:

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 中将域添加到“受信任的角色”。。然后我在Internet Explorer中启动该网站:http://nickis.life:8080nickis.life

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

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:?]

我很困惑。注意:我在这里和那里找到了几个链接,但没有一个像我在这里总结的那样,在所遵循的步骤上都是包罗万象的,而且其中提供的解决方案都没有为我工作。

任何人都可以追踪我在这里搞砸了什么吗?

更新:

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

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)

  • 我在服务器上保存了密钥表更新的文件,然后将服务主体更新为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


答案 1

错误“检测到有缺陷的令牌”可能意味着检测到 令牌。这就是协商机制在 Kerberos 失败时使用的,如果 失败 - 否则不受 Web 服务器的指示。在操作系统上,它上面的IE Web浏览器(以及Firefox,如果配置正确)基本上说,如果你不做Kerberos,我会给你一个NTLM令牌。服务器回复“没办法”我甚至不知道NTLM,所以我称你发给我的东西有缺陷。由于您似乎是第一次设置它,因此您可能没有为 Kerberos 失败时配置任何回退机制(如 NTLM),因此会出现该错误消息。我们通过了解 Kerberos 失败的原因来解决这个问题。我想我在你的问题中看到了失败的原因,在两个地方,与SPN和受信任的站点有关。即使您解决了这两个问题,还有第三个原因和第四个原因可能导致它继续失败,这与加密有关。

  1. HTTP 服务的 与浏览器输入的 URL 不匹配。这些需要匹配,否则 Kerberos 将失败。要工作,浏览器应该使用:http://kerberos500.nickis.life:8080,而不是 http://nickis.life:8080。我根据我在创建语法中看到的内容说这一点。因为您已经将 SPN 编码为:HTTP/kerberos500.nickis.life@NICKIS。生命。这就是您需要使用 http://kerberos500.nickis.life:8080 的原因。当您告诉浏览器转到 http://nickis.life:8080 时,浏览器将不知道如何访问您的Web服务。使用该顶部 URL,浏览器假定它需要查找在 Active Directory上运行的 Web 服务(假定只有 nickis.life 的任何内容都假定在域控制器上运行)。出于安全原因,DC 永远不应运行 Web 服务器。
  2. 你需要在 IE 设置下将 http://kerberos500.nickis.life 添加为受信任的站点。或者,*.nickis.life 也可以。(您称之为受信任的角色,而实际上它被称为受信任的站点)。
  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 身份验证仍将失败。

如何正确重新生成密钥表:当您计划使密钥表与该用户帐户关联时,不应运行 setspn - 将 SPN 添加到 AD 用户的命令。原因是因为密钥表创建命令将 SPN 作为命令的一部分添加到用户帐户。如果你的方案在遵循我上面的建议后不起作用,则需要通过 setspn -D 删除 SPN,如下所示:

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

之后重新生成密钥表,我唯一的更改是我告诉它使用所有加密类型。在身份验证过程中,客户端和服务器将就最强的公用项达成一致。

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 Keytabs – 解释。我经常根据我在这个论坛上看到的问题返回并编辑它。

顺便说一句,HTTP /kerberos500.nickis.life是一个服务主体,而不是你在问题中写的用户主体。我只使用Web浏览器在像这样的HTTP场景中测试Kerberos,我不使用cURL。

如果你认真地研究我上面强调的所有四点,我肯定,你会解决这个问题。

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

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

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

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

  1. 打开组策略管理控制台 (GPMC)。
  2. 编辑默认域策略 GPO。(更安全的做法是创建一个新的域级 GPO 并进行编辑,但这取决于你)。
  3. 导航到“网络安全:配置 Kerberos 允许 >的加密类型”>“Windows 设置>”安全设置>“本地策略”>“安全选项”,然后选中“DES_CBC_MD5”和“DES_CBC_MD5”的“计算机配置>策略”。重要说明:在同一组策略中,还要确保还选中 RC4、AES128 和 AES256 的复选框。这些加密类型不会用于您网站的票证,但它们将用于域中的其他所有内容。好了,你已经离开了对话框并关闭了GPMC。
  4. 在 DC 服务器和客户端上运行“gpupdate /force”命令。
  5. 在客户端上运行“klist 清除”以清除所有 Kerberos 票证。
  6. 在网络浏览器中,清除缓存并删除所有 Cookie。
  7. 确保 DC 服务器允许端口 8080 TCP 入站。
  8. 再试一次。

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

编辑3:避免在同一台计算机上运行Kerberos KDC(DC),客户端和服务器。这是获得“有缺陷的令牌错误”的经典配方,即使您已经做对了其他所有事情。

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


答案 2

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

因此,假设 SPN 是 ,当访问服务时,应通过 访问它,否则,它会引发错误。HTTP/serviceX.domain.comhttp://serviceX.doamin.comDefective token

(我还发现所有与Keberos相关的错误消息都非常令人困惑,也许麻省理工学院故意让它难以理解,相应地会更加难以破解。


推荐