Java中的简单Kerberos客户端?

时间:2011-04-27 12:44:58

标签: java kerberos

Google Chrome和IE等应用程序可以透明地处理Kerberos身份验证;但是,我无法找到一个“简单”的Java解决方案来匹配这种透明度。我发现的所有解决方案都需要存在krb5.conf文件和login.conf文件,而上述应用程序似乎需要这些文件。

使用Kerberos SSO功能构建Java应用程序的最佳方法是什么?

[更新]:要明确我需要一个 CLIENT 端解决方案创建门票而不验证它们。此外,似乎SPNEGO是默认的“包装器”协议,最终将委托给Kerberos,但我也需要能够处理SPNEGO协议。

9 个答案:

答案 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团队的

Example code

Daniel Doubrovkine Timothy Wall Ryan McKinley

的良好工作使这一切成为可能

答案 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获取服务票证:

  1. 使用Krb5LoginModule检索缓存的TGT并将其添加到主题。

  2. 使用Subject和GSS-API从KDC检索服务票证。

  3. 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