浏览器不断发送 NTLM 令牌而不是 Kerberos - 如何解决? [英] Browsers keeps sending NTLM token instead of Kerberos - How to solve it?
问题描述
我似乎无法正确配置系统并让浏览器发送 已配置 Jetty/SPNEgo
支持的 Web 应用程序.
OTHER.COMPANY.local
(在 192.168.0.9
上),只是一个客户端,所以我可以从另一台机器访问软件服务器.最后两个实际上是运行在内网linux
服务器上的VM
.他们可以通过自己的 IP 访问.他们在网络配置
中的主要DNS
指向192.168.0.5
.
两者都加入 COMPANY.local
并在 AD
中作为计算机出现.
我知道客户端和服务器
Internet Explorer(以及 Chrome)在 Internet 选项
中有以下设置:
安全性>本地内联网网站 >*.company.local安全自定义级别仅内网区域自动登录
当我在 http://software.company.local:8998/software/login
我可以看到浏览器发送了一个NTLM
请求
并且我可以在服务器端看到 网络应用程序已注册为 Windows 服务器.
这些是配置文件:
krb5.ini
文件:
[libdefaults]default_realm = COMPANY.LOCALallowed_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96default_tgs_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96default_tkt_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96default_keytab_name = FILE:C:/software/inst/modules/common-config/krb5.keytab[domain_realm]公司.本地 = 公司.本地.company.local = 公司.本地[领域]公司.本地 = {admin_server = PC-I7.COMPANY.localkdc = PC-I7.COMPANY.local:88}
spnego.conf
文件:
com.sun.security.jgss.initiate {需要 com.sun.security.auth.module.Krb5LoginModuleprincipal = "HTTP/software.company.local@COMPANY.LOCAL"keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"useKeyTab = 真商店密钥 = 真调试 = 真isInitiator = false;};com.sun.security.jgss.accept {需要 com.sun.security.auth.module.Krb5LoginModuleprincipal = "HTTP/software.company.local@COMPANY.LOCAL"useKeyTab = 真keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"存储键=真调试=真isInitiator=false;};
这是 spnego.properties
文件:
targetName = HTTP/software.company.local
我的jetty-web.xml
配置文件包含:
<设置名称=登录服务"><New class="org.eclipse.jetty.security.SpnegoLoginService"><Set name="name">公司领域</Set><设置名称=配置"><SystemProperty name="jetty.home" default="."/>/modules/common-config/auth/spnego.properties</Set></新的></设置><设置名称="checkWelcomeFiles">true</Set></获取>
这是我在 Java
中以编程方式注册 spnego
配置的方式:
private SecurityHandler wrapEnableSSOAuthHandlers(final Handler collection) {//ini文件System.setProperty("java.security.krb5.conf",_config.getString("authentication.win_sso.spnego.krb5")//krb5.ini 文件);System.setProperty("java.security.auth.login.config",_config.getString("authentication.win_sso.spnego.login")//spnego.conf 文件);System.setProperty("javax.security.auth.useSubjectCredsOnly",错误的");最终约束 spnegoConstraint = new Constraint();spnegoConstraint.setName(Constraint.__SPNEGO_AUTH);final String domainRealm = _config.getString("authentication.win_sso.domain.realm");//解析为 COMPANY.LOCALspnegoConstraint.setRoles(new String[]{domainRealm});spnegoConstraint.setAuthenticate(true);最终 ConstraintMapping 映射 = new ConstraintMapping();mapping.setConstraint(spnegoConstraint);mapping.setPathSpec("/*");最终字符串 spnegoProperties = _config.getString("authentication.win_sso.spnego.properties");//spnego.properties 文件final SpnegoLoginService loginService = new SpnegoLoginService();loginService.setConfig(spnegoProperties);loginService.setName(domainRealm);final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();securityHandler.setLoginService(loginService);securityHandler.setConstraintMappings(new ConstraintMapping[]{mapping});securityHandler.setRealmName(domainRealm);securityHandler.setAuthenticator(new SpnegoAuthenticator());securityHandler.setHandler(集合);返回 securityHandler;}
和
//这里我禁用了所有调用的 TRACE 方法处理程序wrappedSecurityHandler = wrapDisableTraceHandlers(handlers);WrappedSecurityHandler = wrapEnableSSOAuthHandlers(wrappedSecurityHandler);_server.setHandler(wrappedSecurityHandler);
<小时>
编辑 1:附加信息
我已经下载了 Kerberos 身份验证测试器工具,并从 KDC
服务器 (192.168.0.5
) 运行它并针对 http://software.company.local:8998<进行测试/code> 它显示了正确的
Kerberos
身份验证.
当从 192.168.0.10
服务器(浏览器所在的位置)运行它时,它说:
意外的授权标头
和认证方法:NTLM
.
我想要么是 DNS
问题,要么是因为它们是同一台服务器上的两个 VM
.
显然,将客户端和服务器放在两个不同的虚拟机(在同一 物理服务器上!)可能会导致 NTLM
令牌.
我认为 VM
会避开 client-and-server-on-the-same-机器问题.
所以,如果你
- 像我一样,正在使用位于同一台物理机器上的
VM
进行测试,并且 - 已将一切设置正确,但仍然收到
检测到有缺陷的令牌
,
您应该尝试从另一台计算机访问服务器
(只要该计算机已加入公司域).
I can't seem to correctly configure the system and have the browser send a kerberos ticket to the web-server. Instead, a NTLM
token is sent.
Q: How can I solve this?
All details and configurations are listed below.
Infrastructure:
I have three machines within the domain COMPANY.local
:
PC-I7.COMPANY.local
(on192.168.0.5
). It acts asKDC
, it's anActive-Directory
server with the other machines (see below) registered in the AD. Also has theDNS
for the local network configured. The domain in the Active Directory is:COMPANY.local
SOFTWARE.COMPANY.local
(on192.168.0.10
) runs the web-application which has theJetty/SPNego
support configured.OTHER.COMPANY.local
(on192.168.0.9
), just a client so I can access the software server from another machine.
The last two are actually VM
s running on a linux
server in the intranet. They are reachable with their own IP. Their primary DNS
in Network Configuration
points to 192.168.0.5
.
Both are joined in COMPANY.local
and are present as computers in the AD
.
I know client and server should stay on different machines; and being them onto two different VM
's should avoid this issue.
All three machines are registered as A
hosts in the DNS
with a reverse pointer for each of them in the Reverse lookup zone
.
SPN
After having created the user software
in the Active Directory, I generate the keytab file
ktpass -princ HTTP/software.company.local@COMPANY.LOCAL -mapuser software@COMPANY.LOCAL -crypto ALL -ptype KRB5_NT_PRINCIPAL -pass __PassForADUserSoftware__ -out C:/winnt/krb5.keytab
I get the following output which seems to contain an error:
Targeting domain controller: PC-I7.COMPANY.local
Failed to set property 'userPrincipalName' to 'HTTP/software.company.local@COMPANY.LOCAL' on Dn 'CN=Software SSO Kerberized WebServer,DC=COMPANY,DC=local': 0x13.
WARNING: Failed to set UPN HTTP/software.company.local@COMPANY.LOCAL on CN=Software SSO Kerberized WebServer,DC=COMPANY,DC=local.
kinits to 'HTTP/software.company.local@COMPANY.LOCAL' will fail.
Successfully mapped HTTP/software.company.local to software.
Password successfully set!
Key created.
Key created.
Key created.
Key created.
Key created.
Output keytab to C:/winnt/krb5.keytab:
Keytab version: 0x502
keysize 64 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x1 (DES-CBC-CRC) keylength 8 (0x0bf1688040abadba)
keysize 64 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x3 (DES-CBC-MD5) keylength 8 (0x0bf1688040abadba)
keysize 72 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x17 (RC4-HMAC) keylength 16 (0x737d9811dd38e108741461ba79153192)
keysize 88 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x12 (AES256-SHA1) keylength 32 (0xcc8ab2939f822f9df6904a987954e0cfaa261bc36803af6c5f8d9a98f1d4f2aa)
keysize 72 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x11 (AES128-SHA1) keylength 16 (0xd616b814dcd1b955f125ab4de5895d39)
The AD
user has the two This account supports the Kerbers AES-...
checkboxes checked.
The OTHER.COMPANY.local
server
I login to this machine via RDP
with the credentials:
user: Administrator
pass: ARandomPass
When asking for a ticket from OTHER
server with
kinit HTTP/software.company.local@COMPANY.LOCAL
I can see this packets with wireshark
Internet explorer (and therefore Chrome) have the following settings in Internet Options
:
Security > Local Intranet > Sites > *.company.local
Security > Custom level > Automatic logon only in Intranet area
When I reach the web application on http://software.company.local:8998/software/login
I can see the browser sends a NTLM
request
and I can see the Defective Token exception on the server side
WARN:oejs.SpnegoLoginService:qtp506835709-28:
GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:97)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:306)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
at org.eclipse.jetty.security.SpnegoLoginService.login(SpnegoLoginService.java:138)
at org.eclipse.jetty.security.authentication.LoginAuthenticator.login(LoginAuthenticator.java:61)
at org.eclipse.jetty.security.authentication.SpnegoAuthenticator.validateRequest(SpnegoAuthenticator.java:99)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:483)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)
Also this info appears in the java
log:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false
ticketCache is null isInitiator false
KeyTab is C:/software/inst/modules/common-config/auth/krb5.keytab refreshKrb5Config is false
principal is HTTP/software.company.local@COMPANY.LOCAL tryFirstPass is false
useFirstPass is false storePass is false clearPass is false
Information I can gather from the linked answer:
Point 1: The SPN for the HTTP service does match the URL entered by the browser. I input
software.company.local
in the browser which is the same as the SPNHTTP/software.company.local@COMPANY.LOCAL
Point 2:
*.company.local
is added to the trusted sites.Point 3: I'm not restricting the encrpytion to
DES-CBC-MD5
Point 3: I have checked
AES-128
andAES-256
... but notDES
because the Windows Server version I am working with has the checkbox sayingUse only Kerberos DES encryption types for this account
, which is not what I want. Should I check it?
The SOFTWARE.COMPANY.local
server
The web-application is registered as a Windows Server.
These are the configuration files:
krb5.ini
file:
[libdefaults]
default_realm = COMPANY.LOCAL
permitted_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96
default_tgs_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96
default_tkt_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96
default_keytab_name = FILE:C:/software/inst/modules/common-config/krb5.keytab
[domain_realm]
COMPANY.local = COMPANY.LOCAL
.company.local = COMPANY.LOCAL
[realms]
COMPANY.LOCAL = {
admin_server = PC-I7.COMPANY.local
kdc = PC-I7.COMPANY.local:88
}
spnego.conf
file:
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
principal = "HTTP/software.company.local@COMPANY.LOCAL"
keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"
useKeyTab = true
storeKey = true
debug = true
isInitiator = false;
};
com.sun.security.jgss.accept {
com.sun.security.auth.module.Krb5LoginModule required
principal = "HTTP/software.company.local@COMPANY.LOCAL"
useKeyTab = true
keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"
storeKey=true
debug=true
isInitiator=false;
};
and this is the spnego.properties
file:
targetName = HTTP/software.company.local
My jetty-web.xml
configuration file contains:
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.SpnegoLoginService">
<Set name="name">Company Realm</Set>
<Set name="config">
<SystemProperty name="jetty.home" default="."/>/modules/common-config/auth/spnego.properties</Set>
</New>
</Set>
<Set name="checkWelcomeFiles">true</Set>
</Get>
This is how I programmatically register the spnego
configuration in Java
:
private SecurityHandler wrapEnableSSOAuthHandlers(final Handler collection) {
// ini file
System.setProperty(
"java.security.krb5.conf",
_config.getString("authentication.win_sso.spnego.krb5") // the krb5.ini file
);
System.setProperty(
"java.security.auth.login.config",
_config.getString("authentication.win_sso.spnego.login") // the spnego.conf file
);
System.setProperty(
"javax.security.auth.useSubjectCredsOnly",
"false"
);
final Constraint spnegoConstraint = new Constraint();
spnegoConstraint.setName(Constraint.__SPNEGO_AUTH);
final String domainRealm = _config.getString("authentication.win_sso.domain.realm"); // resolves to COMPANY.LOCAL
spnegoConstraint.setRoles(new String[]{domainRealm});
spnegoConstraint.setAuthenticate(true);
final ConstraintMapping mapping = new ConstraintMapping();
mapping.setConstraint(spnegoConstraint);
mapping.setPathSpec("/*");
final String spnegoProperties = _config.getString("authentication.win_sso.spnego.properties"); // the spnego.properties file
final SpnegoLoginService loginService = new SpnegoLoginService();
loginService.setConfig(spnegoProperties);
loginService.setName(domainRealm);
final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
securityHandler.setLoginService(loginService);
securityHandler.setConstraintMappings(new ConstraintMapping[]{mapping});
securityHandler.setRealmName(domainRealm);
securityHandler.setAuthenticator(new SpnegoAuthenticator());
securityHandler.setHandler(collection);
return securityHandler;
}
and
// here I disable the TRACE method for all calls
Handler wrappedSecurityHandler = wrapDisableTraceHandlers(handlers);
wrappedSecurityHandler = wrapEnableSSOAuthHandlers(wrappedSecurityHandler);
_server.setHandler(wrappedSecurityHandler);
EDIT 1: Additional info
I have downloaded the Kerberos Authentication Tester Tool and when running it from the KDC
server (192.168.0.5
) and testing against http://software.company.local:8998
it shows a correct Kerberos
authentication.
When running it from the 192.168.0.10
server (where the browser is) it says:
Unexpected authorization header
and authentication method: NTLM
.
I guess it's either a DNS
issue or the fact that they are two VM
on the same server.
Apparently, having client and server on two distinct virtual machines ( that are on the same physical server! ) can lead to a NTLM
token.
I thought VM
's would dodge the client-and-server-on-the-same-machine-issue.
So, if you
- like me, are testing with
VM
's residing on the same physical machine, and - have set everything right but still getting a
Defective token detected
,
you should try to access the server
from a different computer (as long as that machine is joined to the company domain).
这篇关于浏览器不断发送 NTLM 令牌而不是 Kerberos - 如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!