“检测到 GSSException 有缺陷的令牌"- 尝试使用 Kerberos 对在 Windows 上运行的 Tomcat 进行身份验证时 [英] "GSSException Defective token detected" - when trying to Authenticate to Tomcat running on Windows using Kerberos

查看:39
本文介绍了“检测到 GSSException 有缺陷的令牌"- 尝试使用 Kerberos 对在 Windows 上运行的 Tomcat 进行身份验证时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am struggling to authenticate to a Java web container (I've tried both Tomcat and Jetty) when running on Windows 2012.

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

Every time I try the Negotiate auth scheme I get an error: org.ietf.jgss.GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)

重现步骤

首先设置 Windows Server 2012 或 2016 实例并安装 Active Directory 域服务.

Start out by setting up a Windows Server 2012 or 2016 instance and install active directory domain services.

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

In my example, I created:

  • NETBIOS 域: NICKIS

Dns 域: nickis.life

Dns domain: nickis.life

在 Active Directory 上创建 kerberos 主题用户

Create the kerberos subject user on Active Directory

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

IMPORTANT: MAKE SURE THAT THE FIRST NAME, LAST NAME AND FULL NAME ARE THE SAME!

就我而言,新用户是:

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

登录+域名 = kerberos500@nickis.life

NETBIOSsamAccountName = NICKISkerberos500

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

Run the setspn command from the Windows Active Directory Server

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

示例输出:

C:UsersAdministrator>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 命令

Run the ktpass command from the Windows Active Directory Server

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

示例输出:

C:UsersAdministrator>ktpass -out c:UsersAdministratorkerberos500.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:UsersAdministratorkerberos500.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.

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

At this point, you will now have a keytab file:

c:UsersAdministratorkerberos500.keytab

还有一个用户主体:

HTTP/kerberos500.nickis.life@NICKIS.LIFE

这些是提供给 GSSApi 以使用 Kerberos 进行单点登录所需的 2 个输入.

These are the 2 inputs that are needed to provide to the GSSApi to get single sign on with Kerberos.

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

So I deployed those inputs to my web container's kerberos security realm in the Hadoop security module.

curl 测试 我尝试使用 curl 测试没有成功:

Curl test I tried unsuccessfully to use curl to test it:

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

Internet Explorer 测试 我也尝试使用 Internet Explorer.我将 nickis.life 域添加到 Internet Explorer 中的受信任角色.然后我在 Internet Explorer 中启动该站点:http://nickis.life:8080

Internet Explorer test I also tried using Internet Explorer. I added nickis.life domain to the Trusted Roles in Internet Explorer. Then I launch the site in internet explorer: http://nickis.life:8080

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

Either way, I get the error below:

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

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

I am stumped. NOTE: I have found several links around here and there but none of them were all inclusive on the steps that were followed like I have summed up here, and none of the solutions provided within worked for me.

有人能查出我在这里搞砸了什么吗?

Can anyone trace what I am screwing up here?

更新:

  • 我有域设置为fusionis.life的AD服务器,AD服务器是WIN-OVV6VHBGIB8.fusionis.life
  • 我将 tomcat 服务器移到域中的另一台 Windows 机器上.DESKTOP-VTPBE99.fusionis.life
  • 我打开了 dnsmgmt.msc 并添加了一个带有kerberos500.nickis.life"的正向查找区域",其中一个 HOST 设置为 DESKTOP-VTPBE99.fusionis.life 的 IP 框.
  • 我删除了 AD 帐户,重新创建了它,然后按照票证上的一个答案中的建议再次重新生成了密钥表.
  • I have AD server with domain set to fusionis.life, and the AD server is WIN-OVV6VHBGIB8.fusionis.life
  • I moved the tomcat server to another windows machine in the domain. DESKTOP-VTPBE99.fusionis.life
  • I opened dnsmgmt.msc and added a "Forward Lookup Zone" with "kerberos500.nickis.life" with A HOST set to the IP of the DESKTOP-VTPBE99.fusionis.life box.
  • I deleted the AD account, recreated it, then re-generated the keytab again as suggested in one of the answers on the ticket.

<代码>C:UsersAdministrator>ktpass -out c:UsersAdministratorkerberos500.keytab -princ HTTP/kerberos500.nickis.life@NICKIS.LIFE -mapUser kerberos500 -mapOp set -pass xxxxxxxxx -crypto ALL -pType KRBAL5_NT_PRINCIP目标域控制器:WIN-OVV6VHBGIB8.fusionis.life使用旧密码设置方法成功将 HTTP/kerberos500.nickis.life 映射到 kerberos500.密钥已创建.密钥已创建.密钥已创建.密钥已创建.密钥已创建.将密钥表输出到 c:UsersAdministratorkerberos500.keytab:密钥表版本:0x502密钥大小 67 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x1 (DES-CBC-CRC) 密钥长度 8 (0x04e30b9183ba8389)密钥大小 67 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x3 (DES-CBC-MD5) 密钥长度 8 (0x04e30b9183ba8389)keysize 75 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x17 (RC4-HMAC) keylength 16 (0xe39a141de38abd8750bf9c0bf49fd1c5)密钥大小 91 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x12 (AES256-SHA1) 密钥长度 32 (0xe368a1b060cfe4816f522c1c5f260202c1c5f260205c5f6040d1b9d58c58c58c58dc59d5c59d58c5602d59d58c562dfb9d59d58c59d5c5602d12d59d59d58c582d8c5602d8c12d25662d2012d59d58c582d5c862d2012d59d58c59d59d5c12d2061200x12etype 0x12 (AES256-SHA1) 密钥长 度 91密钥大小 75 HTTP/kerberos500.nickis.life@NICKIS.LIFE ptype 1 (KRB5_NT_PRINCIPAL) vno 4 etype 0x11 (AES128-SHA1) 密钥长度 16 (0x1b1a548fa2893a78c6f4c7f9c482b66

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

我以域用户身份登录 tomcat 机器,添加了 http://kerberos500.nickis.life 到受信任的站点,然后导航到 http://kerberos500.nickis.life:8764

I logged into tomcat machine as a domain user, added http://kerberos500.nickis.life to the trusted sites, then navigated to http://kerberos500.nickis.life:8764

我检查了 kerberos500 AD帐户"选项卡中加密复选框的所有组合.

I checked all combinations of the encryption check boxes in the kerberos500 AD "account" tab.

现在我收到一个新错误...

Now i'm getting a new error...

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

更新:

终于解决了.我得到最后一个错误是因为我需要 fusionis.lifenickis.life

Resolved finally. I got this final error because I needed fusionis.life to be on the same host as nickis.life

推荐答案

错误Defective token detected"可能意味着 标记被检测到.如果 失败 - 否则 Web 服务器未指示时.在 操作系统上,IE 网络浏览器就可以了(和 Firefox,如果配置正确)基本上是说,如果您不使用 Kerberos,我将向您发送一个 NTLM 令牌.服务器回复不可能",我什至不知道 NTLM,所以我说你发送给我的东西有缺陷.由于您似乎是第一次进行设置,因此您可能没有为 Kerberos 失败时配置任何回退机制(例如 NTLM),因此,该错误消息.我们通过了解 Kerberos 失败的原因来解决这个问题.我想我在与 SPN 和可信站点相关的两个地方看到了您问题中失败的原因.即使您解决了这两个项目,还有第三个和第四个原因可能会继续失败,这与加密有关.

The error "Defective token detected" likely means that an ntlm token was detected. That’s what the Negotiate mechanism uses inside popular web browsers if kerberos fails - when not instructed by the web server otherwise.  On windows operating systems, the IE web browser on it (and Firefox, if configured correctly) basically says, if you won’t do Kerberos, I’m going to send you an NTLM token.  And the server replies "no way" I don’t even know NTLM so I’m calling what you sent me defective.  Since you seem to be setting this up for the first time, you likely did not configure any fallback mechanism (such as NTLM) for when Kerberos fails, therefore, that error message. We solve this by understanding why Kerberos is failing.  I think I see the reason for the failure in your question, in two places, related to SPNs and Trusted Sites. Even if you resolve those two items, there is a third reason and fourth reason why it could continue to fail, related to encryption.

  1. 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 时,浏览器将不知道如何访问您的 Web 服务.使用该顶级 URL,浏览器假定它需要找到在您的 Active Directory 上运行的 Web 服务(假设只有 nickis.life 的任何东西都在域控制器上运行).出于安全原因,DC 不应运行网络服务器.
  2. 您需要在 IE 设置下将 http://kerberos500.nickis.life 添加为受信任站点.或者, *.nickis.life 也可以.(您将其称为受信任的角色,而实际上称为受信任的站点).
  3. 您将 Kerberos 加密类型限制为 DES-CBC-MD5.从 Windows Server 2008 Active Directory R2 开始,默认情况下禁用 DES.如今,DES 是一种过时且普遍不安全的加密类型.使用 AES128 更好,甚至更好,使用 AES256.您可以按照下面的示例重新生成密钥表来解决此问题.
  4. 在 AD 用户帐户 kerberos500 中,转到帐户"选项卡,滚动到底部,然后选中 DES、AES 128 和 AES 256 的所有框,然后您就可以退出对话框了.即使您按照上面的步骤进行了所有操作,也必须选中这些框,否则 Kerberos 身份验证仍然会失败.
  1. The spn for the HTTP service does not match the URL entered by the browser. These need to match, otherwise Kerberos will fail. To work, the browser should be using: http://kerberos500.nickis.life:8080, not http://nickis.life:8080. I say that based on what I saw in your keytab creation syntax. In that you’ve coded the SPN as such: HTTP/kerberos500.nickis.life@NICKIS.LIFE. That’s why you need to use http://kerberos500.nickis.life:8080. The browser won’t know how to get to your web service when you tell it to go to http://nickis.life:8080. With that top URL, the browser assumes it needs to find a web service running on your Active Directorydomaincontroller (anything with just nickis.life is assumed to run on the Domain Controller). DCs should never run web servers for security reasons.
  2. You’ll need to add http://kerberos500.nickis.life as a Trusted Site under IE settings. Alternatively, *.nickis.life would work as well. (You called it Trusted Roles, when it’s actually called Trusted Sites).
  3. You are restricting the Kerberos encryption type to DES-CBC-MD5. Starting with Windows Server 2008 Active Directory R2, DES is disabled by default. DES is an outdated and generally insecure encryption type these days. Much better to use AES128 or even better, AES256. You can fix that by re-generating the keytab per my example below.
  4. In the AD user account kerberos500, go to the Account tab, scroll to the bottom, and check all the boxes for DES, AES 128, and AES 256, and OK you’re way out of the dialog boxes. You must check these boxes even if you did everything right above, or else Kerberos authentication will still fail.

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

How to properly re-generate the keytab: You should not run the setspn -a command to add an SPN to an AD user whenever you are planning to make a keytab associated with that user account.  The reason why is because the keytab creation command adds the SPN to the user account as part of the command.  If your scenario doesn’t work after following my advice above, then you’ll need to remove the SPN via setspn -D like below:

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

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

And the re-generate the keytab afterwards, my only change is that I told it to use all encryption types. The client and server will agree on the strongest common one during the authentication process. 

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


然后用新的密钥表替换旧的密钥表.有关密钥表的其他深入信息,您可以在我的关于如何在此处创建 Kerberos 密钥表的技术文章中阅读更多信息:Kerberos Keytabs – 解释.我经常返回并根据我在此论坛中看到的问题对其进行编辑.


Then replace the old keytab with the new one. For additional in-depth information on keytabs, you can read more from my technical article on how to create Kerberos keytabs here: Kerberos Keytabs – Explained. I frequently go back and edit it based on questions I see here in this forum.

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

By the way, HTTP/kerberos500.nickis.life is a service principal, not a user principal as you wrote in your question. I only use web browsers to test Kerberos in HTTP scenarios like this one, I don’t use cURL.

我很肯定,如果您认真完成我上面强调的所有四点,您就会解决这个问题.

I am positive if you diligently go through all four points I’ve highlighted above, you will resolve this problem.

此答案假设您在具有完全限定域名 kerberos500.nickis.life 的主机上运行 HTTP 服务.如果你没有这个名字的主机,我的答案会略有变化.如果有的话请告诉我.

This answer assumes you have an HTTP service running on a host with the fully-qualified domain name of kerberos500.nickis.life. If you don't have such a host with that name, my answer will slightly change. Please let me know if any.

使用http://nickis.life的URL来达到认证的目的:8080,那么您可以继续使用您已经创建的相同密钥表.

To achieve the objective of authentication using the URL of http://nickis.life:8080, then you may keep on using the same keytab you already created.

在 AD 帐户 NICKISkerberos500 上,转到帐户"选项卡,滚动到底部,然后选中为此帐户使用 Kerberos DES 加密类型"框.

On the AD account NICKISkerberos500, go to the Account tab, scroll to the bottom, and check the box for "Use Kerberos DES encryption types for this account".

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

Then enable DES encryption itself at the AD domain level via Group Policy. To do that, conduct the following:

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

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

编辑 3:避免在 同一台机器.即使您已正确完成其他所有操作,这也是获得缺陷令牌错误"的经典方法.

EDIT 3: Avoid running Kerberos KDC (the DC), client and server on the same machine. That is a classic recipe for getting the "Defective token error" even if you've done everything else right.

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

EDIT 4: (Final update which was verified by the OP): Looked at the new ktpass keytab creation output, and I saw this: Targeting domain controller: WIN-OVV6VHBGIB8.fusionis.life. Now, the defined SPN in the keytab is HTTP/kerberos500.nickis.life. The AD domain name is different from the SPN you defined, so this is not going to work unless you have some kind of trust setup between these domains. If you don't have a trust, you need to use an SPN of HTTP/kerberos500.fusionis.life instead.

这篇关于“检测到 GSSException 有缺陷的令牌"- 尝试使用 Kerberos 对在 Windows 上运行的 Tomcat 进行身份验证时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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