【发布时间】:2011-02-27 17:41:58
【问题描述】:
我们无法让 Spring Security/Kerberos/AD 为我们的 Web 应用程序工作。我们的诊断是我们的 AD 服务器向 IE 发送了一个 NTLM 令牌(我们可以知道它以“TlRMTVNT .....”开头),然后 IE 将它发送到我们的应用程序并且它失败了。我们的 AD 服务器应该向 IE 发送 Kerberos/SPNEGO 令牌。
“活动部件”如下:
- Spring Security 3.0(已修补)
- Microsoft Windows Server Enterprise 2003 SP1 活动目录
- IE 8
- Tomcat(TC 服务器 6.0)
- Java 1.6
我们已按照此处的说明进行了详细设置:
https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension
这涉及到:
- 创建一个普通用户作为服务主体(与我们的应用程序所在的机器名称相同)。我们设置以下帐户选项:
- disabled 'Use has to change password at next login'
- 启用“密码永不过期”
- 启用“使用 Kerberos DES…”
- disabled '不需要 Kerberos 预身份验证'
- 注意:Server 2003 不提供“此帐户支持 Kerberos AES 128 位...”和“此帐户支持 Kerberos AES 256 位...”选项
- 使用“ktpass.exe”将服务主体名称 (SPN) 分配给此新用户并将此用户密钥导出到密钥表文件。使用 'ktpass /out ourweb.keytab /mapuser ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK /princ HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK /pass * '
- 从https://src.springframework.org/svn/se-security/trunk下载源代码。
- 将keytab文件从AD服务器复制到源代码(应用程序)的WEB-INF/etc。
- 更改文件 SunJaasKerbersoTicketValidator.java 以读取 keytab 文件。 (解决应用程序无法从 Java 类路径读取 keytab 文件的问题) options.put("keyTab", "C:\se-security\spring-security-kerberos\spring-security-kerberos-sample\src\main\webapp\WEB-INF\etc\ourweb.keytab");李>
- 将 web.xml 配置为使用 spnego.xml。
上下文配置位置
/WEB-INF/spnego.xml
- 通过提供我们的服务主体名称和 keytab 文件位置,将 Spring Security (spnego.xml) 配置为使用 Kerberos(SpnegoEntryPoint、SpnegoAuthenticationProcessingFilter 和 KerberosServiceAuthenticationProvider bean)。
- 配置 spnego.xml 以读取在 WEB-INF/etc 中复制的 keytab 文件。
当我们启动我们的 TC 服务器时,我们可以看到一切都很好地初始化(即没有错误 - “从 keytab 获得的原则密钥”):
Creating instance of bean 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8'
Invoking afterPropertiesSet() on bean with name 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8'
Config name: C:\WINDOWS\krb5.ini
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is C:\se-security\spring-security-kerberos\spring-security-kerberos-sample\src\main\webapp\WEB-INF\etc\ourwebapp4.keytab refreshKrb5Config is false principal is HTTP/ourwebappweb4.testdomain.ourcompany.co.uk tryFirstPass is false useFirstPass is false storePass is false clearPass is false
>>> KeyTabInputStream, readName(): TESTDOMAIN.OURCOMPANY.CO.UK
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): ourweb
>>> KeyTab: load() entry length: 78; type: 1
>>> KeyTabInputStream, readName(): TESTDOMAIN.OURCOMPANY.CO.UK
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): ourweb.testdomain.ourcompany.co.uk
>>> KeyTab: load() entry length: 113; type: 1
Added key: 1version: 2
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 1.
0: EncryptionKey: keyType=1 kvno=2 keyValue (hex dump)=
0000: 91 01 43 E3 02 A8 B9 83
principal's key obtained from the keytab
principal is HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK
EncryptionKey: keyType=1 keyBytes (hex dump)=0000: 91 01 43 E3 02 A8 B9 83
Added server's keyKerberos Principal HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UKKey Version 2key EncryptionKey: keyType=1 keyBytes (hex dump)=
0000: 91 01 43 E3 02 A8 B9 83
[Krb5LoginModule] added Krb5Principal HTTP/ourweb.testdomain.ourcompany.co.uk@TESTDOMAIN.OURCOMPANY.CO.UK to Subject Commit Succeeded
Finished creating instance of bean 'org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator#10fa4b8'
准备好进行测试,然后我们在 IE 中启用“Windows 集成身份验证”,并确保该域在 IE 的本地 Intranet 站点部分中列出。然后,我们使用完全限定域名连接到我们的 Web 应用程序。
当我们这样做时,我们在浏览器中收到以下错误:
500 Internal server error.
在 TC Server 日志文件中:
Negotiate Header was invalid: Negotiate TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw==
org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesfull
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:74)
at org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:92)
at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:120)
at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48)
at org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:132)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at com.springsource.metrics.collection.web.HttpRequestMetricCollectionValve.invoke(HttpRequestMetricCollectionValve.java:44)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:379)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.security.PrivilegedActionException: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:72)
... 25 more
Caused by: GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:80)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:287)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:161)
at org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:1)
... 28 more
SecurityContextHolder now cleared, as request processing completed
似乎(据我们所知)AD 服务器向 IE 发送 NTLM 令牌(我们可以知道它以“TlRMTVNT .....”开头),然后 IE 将其发送到我们的应用程序,然后它失败了。
我们的 AD 服务器应该向 IE 发送一个 Kerberos/SPNEGO 令牌。
其他说明:
- 我们的服务器(tc 服务器)和客户端(浏览器)在不同的(虚拟)机器上并且在同一个域中。
【问题讨论】:
-
只想说这是我在 SO,超级工作中看到的最详细的问题之一!
标签: java spring-security kerberos