有三种认证协议可用于在Linux或任何其他平台上执行Java和Active Directory之间的身份验证(这些不仅适用于HTTP服务):
Kerberos - Kerberos提供单点登录(SSO)和委派,但Web服务器还需要SPNEGO支持才能通过IE接受SSO。
NTLM - NTLM支持通过IE进行SSO(如果其他浏览器正确配置,则还支持其他浏览器)。
LDAP - LDAP绑定可用于简单验证帐户名和密码。
还有一种称为“ADFS”的东西,它使用调用Windows SSP的SAML为网站提供SSO,因此实际上是使用上述其他协议的迂回方式。
每个协议都有其优点,但通常应尽量“按照Windows的做法”以实现最大兼容性。那么Windows怎么做呢?
首先,两台Windows机器之间的身份验证偏爱Kerberos,因为服务器不需要与DC通信,并且客户端可以缓存Kerberos票据,从而减轻了DC的负载(因为Kerberos支持委派)。
但是,如果验证方不都具有域帐户,或者如果客户端无法与DC通信,则需要NTLM。因此,Kerberos和NTLM并不是相互排斥的,而且NTLM并没有被Kerberos淘汰。实际上,在某些方面,NTLM比Kerberos更好。请注意,当在同一句话中提到Kerberos和NTLM时,我还必须提到SPENGO和集成Windows身份验证(IWA)。 IWA是一个简单的术语,基本上意味着Kerberos或NTLM或SPNEGO来协商Kerberos或NTLM。
使用LDAP绑定作为验证凭据的方法不高效且需要SSL。但是,直到最近实现Kerberos和NTLM一直很困难,因此使用LDAP作为临时身份验证服务仍然存在。但是,现在应该尽量避免使用它。LDAP是信息目录而不是身份验证服务。请将其用于预期目的。
那么,如何在Java中以及特别是在Web应用程序的上下文中实现Kerberos或NTLM呢?
有许多大公司(如Quest Software和Centrify)提供专门针对Java的解决方案。我无法对此发表评论,因为它们是公司范围的“身份管理解决方案”,因此从其网站的营销宣传中很难确定使用了哪些协议以及如何使用。您需要联系他们了解详细信息。
在Java中实现Kerberos并不是非常困难,因为标准Java库通过org.ietf.gssapi类支持Kerberos。但是,直到最近还存在一个重要障碍-IE不发送原始Kerberos令牌,而是发送SPNEGO令牌。但是,随着Java 6的推出,SPNEGO已经得到实现。理论上,您应该能够编写一些GSSAPI代码来验证IE客户端。但我没有尝试过。多年来,Sun的Kerberos实现一直是一个笑话,因此基于Sun在这个领域的记录,我不会对他们的SPENGO实现做出任何承诺,直到您掌握了这个技术。
对于NTLM,有一个名为JCIFS的免费OSS项目,它具有NTLM HTTP身份验证Servlet过滤器。但是,它使用中间人方法来验证凭据与不支持NTLMv2(这正在逐渐成为必需的域安全策略)的SMB服务器。因此,JCIFS的HTTP过滤器部分将被删除。请注意,有许多衍生项目使用JCIFS来实现相同的技术。因此,如果您看到其他声称支持NTLM SSO的项目,请查看详细信息。
使用NetrLogonSamLogon DCERPC调用通过NETLOGON和Secure Channel验证NTLM凭据与Active Directory的唯一正确方法。Java中是否存在这样的东西?是的。在这里:
http://www.ioplex.com/jespa.html
Jespa 是一个完全由 Java 实现的 NTLM 库,支持 NTLMv2、NTLMv1、完整性和机密性选项以及前面提到的 NETLOGON 凭证验证。它包括一个 HTTP SSO 过滤器、JAAS LoginModule、HTTP 客户端、SASL 客户端和服务器(带有 JNDI 绑定)、用于创建自定义 NTLM 服务的通用“安全提供程序”等功能。