Google Chrome和IE等应用程序可以透明地处理Kerberos身份验证;但是,我无法找到一个“简单”的Java解决方案来匹配这种透明度。我发现的所有解决方案都需要存在krb5.conf文件和login.conf文件,而上述应用程序似乎需要这些文件。
使用Kerberos SSO功能构建Java应用程序的最佳方法是什么?
[更新]:要明确我需要一个 CLIENT 端解决方案创建门票而不验证它们。此外,似乎SPNEGO是默认的“包装器”协议,最终将委托给Kerberos,但我也需要能够处理SPNEGO协议。
答案 0 :(得分:12)
现在有一个简单的解决方案,使用Apache HTTP Components Client 4.5或更高版本。这在4.5中仍然标记为实验性,因此您的milage可能会有所不同,但在企业环境中这对我来说很好。
除了HC 4.5客户端jar之外,您还需要在类路径中使用httpclient-win,jna和jna-platform jar,如http-component-client所示。然后,您构建一个启用Kerberos的HC客户端,如下所示:
CloseableHttpClient httpclient = WinHttpClients.createDefault();
或使用构建器:
HttpClientBuilder clientBuilder = WinHttpClients.custom();
然后可以在构建客户端之前根据需要自定义:
CloseableHttpClient client = clientBuilder.build();
此解决方案无需任何外部配置即可运行,最重要的是解决了内置JRE机制在Windows 7+上具有本地管理员权限的用户中断的问题。这是可能的,因为Kerberos票证是通过JNA直接从SSPI API检索的,而不是通过JRE提供的GSSAPI。
来自http-components团队的 的良好工作使这一切成为可能答案 1 :(得分:9)
添加到David Roussels关于url特定基于http的kerberos身份验证的答案: -
您的代码工作的原因是您的目标SPN(服务器端主体)配置为使用HTTP /serverhostname.realm.com@DOMAIN.COM。在这种情况下,它将起作用,因为您没有明确设置令牌。 URLConnection在内部设置具有该SPN的令牌
1执行步骤(来自我之前的回答)以获得主题
2使用gss api init sec context生成上下文令牌。这一步有很多教程
3 Base 64编码令牌
4将令牌附加到urlconnection: -
URL url = new URL("http://myhost/myapp")
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); =
urlConn.setRequestProperty("Authorization", "Negotiate " + encodedToken);
5实施特权行动: -
//this internally calls the getInputStream
public class PrivilegedGetInputStream implements PrivilegedExceptionAction<InputStream>
6将整个事物包裹在Subject.doAs
中//use prev answer instructions to get subject
Subject.doAs(subject, new PrivilegedGetInputStream(urlConnection)
答案 2 :(得分:8)
Oracle有an example using Java's SaslClient。我不是一名Java程序员,但是当我向某个人指出这一点时,他们能够很快地使它工作。它可能仍然需要某处的“conf”文件(n.b. Kerberos使用环境变量,通常以KRB5_开头,以了解在哪里查找此类文件)。另请注意,Kerberos本身不包含任何类型的传输 - 您的应用程序需要知道如何以服务器期望的方式发送和接收Kerberos有效负载(这取决于您尝试进行身份验证的服务器)。
编辑:你编辑了你的问题,所以这里有一个与Java中的SPNEGO相关的链接,可能有一些用处: http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html
答案 3 :(得分:7)
你实际上并不需要做任何事情。在Java 6中,在Windows客户端计算机上,您可以执行此操作:
new URL("http://myhost/myapp").openStream();
协商身份验证才有效。至少它对我有用。我测试的服务器只支持Negotiate,而不支持NTLM auth。
答案 4 :(得分:4)
好的,如果你想避免使用login.conf文件,你需要采用不同的代码: -
//define your own configuration
import javax.security.auth.login.Configuration;
public class CustomLoginConfiguration extends Configuration
//pass certain parameters to its constructor
//define an config entry
import javax.security.auth.login.AppConfigurationEntry;
private AppConfigurationEntry configEntry;
//define a map of params you wish to pass and fill them up
//the map contains entries similar to one you have in login.conf
Map<String, String> params = new HashMap<String, String>();
//define the configuration
configEntry = new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, params);
//implement getappconfig method
public AppConfigurationEntry[] getAppConfigurationEntry() {
return new AppConfigurationEntry[] { configEntry };
}
现在,一旦你完成了这个定义,你可以使用它来使用它从kdc获取票证
//get ticket in login context
LoginContext lc = null;
lc = new LoginContext("lc", null, callback, new CustomLoginConfiguration(argumentlist));
lc.login();
现在从这里开始你可以获取jaas主题,基本上可以做很多认证。
如果您需要更多指示,请发表评论。
答案 5 :(得分:2)
您可以使用系统属性而不是配置文件来指定KDC主机名和服务名称,但这些(至少)是强制性的....
Waffle实际上会为您提供设置大部分属性所需的信息,即使它不会为您提供票证。查看WindowsAuthProviderImpl类(Waffle.chm帮助文件显示API)。
我使用JAAS通过两个步骤从Active Directory获取服务票证:
使用Krb5LoginModule检索缓存的TGT并将其添加到主题。
使用Subject和GSS-API从KDC检索服务票证。
The Java Way of Active Directory上有很多好的信息和示例代码。
答案 6 :(得分:1)
我创建了一个小工具来简化与httpclient与kerberos的连接,你可能想尝试一下。 https://github.com/DovAmir/httpclientAuthHelper
DefaultHttpClient httpclient = new DefaultHttpClient();
AuthUtils.securityLogging(SecurityLogType.KERBEROS,true);
CredentialsUtils.setKerberosCredentials(client, new UsernamePasswordCredentials("xxx", "xxx"), "domain", "kdc");
client.executeMethod(httpget);
答案 7 :(得分:0)
使用WAFFLE
答案 8 :(得分:0)
这是一篇关于让Java客户端与Kerberos一起使用的好文章 http://sachithdhanushka.blogspot.com/2014/02/kerberos-java-client-configuration.html