简体   繁体   English

Java中的简单Kerberos客户端?

[英]Simple Kerberos client in Java?

Applications such a Google's Chrome and IE can transparently handle Kerberos authentication; 谷歌的Chrome和IE等应用程序可以透明地处理Kerberos身份验证; however I can not find a "simple" Java solution to match this transparency. 但是,我无法找到一个“简单”的Java解决方案来匹配这种透明度。 All of the solutions I have found require the presence of a krb5.conf file and a login.conf file which nether of the above apps seem to require. 我发现的所有解决方案都需要存在krb5.conf文件和login.conf文件,而上述应用程序似乎需要这些文件。

What is the best way to build a Java application with Kerberos SSO capabilities that just work? 使用Kerberos SSO功能构建Java应用程序的最佳方法是什么?

[update]: to be clear I need a CLIENT side solution for creating tickets not validating them. [更新]:要明确我需要一个CLIENT端解决方案来创建不验证它们的票证 Also, it seems that SPNEGO is the default "wrapper" protocol that will eventually delegate to Kerberos but I need to be able to handle the SPNEGO protocol as well. 此外,似乎SPNEGO是默认的“包装器”协议,最终将委托给Kerberos,但我也需要能够处理SPNEGO协议。

There is now a simple solution for this using the Apache HTTP Components Client 4.5 or greater. 现在有一个使用Apache HTTP Components Client 4.5或更高版本的简单解决方案。 This is still marked as experimental in 4.5 so your milage may vary, but this is working fine for me in an enterprise context. 这在4.5中仍然标记为实验性,因此您的milage可能会有所不同,但在企业环境中这对我来说很好。

In addition to the HC 4.5 client jars you will need to have the httpclient-win, jna and jna-platform jars on your classpath, as provided with http-component-client. 除了HC 4.5客户端jar之外,您还需要在类路径中使用httpclient-win,jna和jna-platform jar,如http-component-client所提供。 You then construct a Kerberos enabled HC-client as follows: 然后,您构建一个启用Kerberos的HC客户端,如下所示:

CloseableHttpClient httpclient = WinHttpClients.createDefault();

Or using the builder: 或者使用构建器:

HttpClientBuilder clientBuilder = WinHttpClients.custom();

Which can then be customised as required before building the client: 然后可以在构建客户端之前根据需要对其进行自定义:

CloseableHttpClient client = clientBuilder.build();

This solution works without any external configuration, and most importantly solves the issue where the in-built JRE mechanism breaks for users with local Admin rights on Windows 7+. 此解决方案无需任何外部配置即可运行,最重要的是解决了内置JRE机制在Windows 7+上具有本地管理员权限的用户中断的问题。 This is possible because the Kerberos ticket is being retrieved directly from the SSPI API via JNA, rather than going through the GSSAPI provided by the JRE. 这是可能的,因为Kerberos票证是通过JNA直接从SSPI API检索的,而不是通过JRE提供的GSSAPI。

Example code from the http-components team 来自http-components团队的示例代码

This was all made possible by the good work of Daniel Doubrovkine Timothy Wall and Ryan McKinley Daniel Doubrovkine Timothy WallRyan McKinley的出色工作使这一切成为可能

Adding to David Roussels answer on url specific http based kerberos authentication:- 添加到David Roussels关于url特定基于http的kerberos身份验证的答案: -

The reason why your code works is because your target SPN(server side principal) is configured to with HTTP/serverhostname.realm.com@DOMAIN.COM. 您的代码工作的原因是因为您的目标SPN(服务器端主体)配置为HTTP /serverhostname.realm.com@DOMAIN.COM。 In that case it will work because you are not explicitly setting the token. 在这种情况下,它将起作用,因为您没有明确设置令牌。 URLConnection internally sets a token with that SPN URLConnection在内部使用该SPN设置令牌

1 Perform steps(from my previous answer) to get a subject 1执行步骤(来自我之前的答案)以获得主题

2 Use gss api init sec context to generate a context token. 2使用gss api init sec context生成上下文令牌。 There are numerous tutorials out there for this step 这一步有很多教程

3 Base 64 encode the token 3 Base 64编码令牌

4 Attach the token to urlconnection:- 4将令牌附加到urlconnection: -

URL url = new URL("http://myhost/myapp")
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); = 
urlConn.setRequestProperty("Authorization", "Negotiate " + encodedToken);

5 Implement a priviledged action:- 5实施特权行动: -

//this internally calls the getInputStream
public class PrivilegedGetInputStream implements PrivilegedExceptionAction<InputStream>

6 Wrap the whole thing in Subject.doAs 6将整个东西包裹在Subject.doAs中

//use prev answer instructions to get subject
Subject.doAs(subject, new PrivilegedGetInputStream(urlConnection)

Oracle has an example using Java's SaslClient . Oracle有一个使用Java的SaslClient的例子 I'm not a Java programmer, but when I pointed this out once to someone who is, they were able to make it work pretty quickly. 我不是一名Java程序员,但是当我向某个人指出这一点时,他们能够很快地使它工作。 It may still require a "conf" file somewhere (nb Kerberos uses environment variables, often starting with KRB5_, to know where to look for such files). 它可能仍然需要某处的“conf”文件(nb Kerberos使用环境变量,通常以KRB5_开头,以了解在哪里查找此类文件)。 Also note that Kerberos itself does not include a transport of any kind--your app needs to know how to send and receive the Kerberos payloads the way the server expects (and this is different depending on the server you are trying to authenticate with). 另请注意,Kerberos本身不包含任何类型的传输 - 您的应用程序需要知道如何以服务器期望的方式发送和接收Kerberos有效负载(这取决于您尝试进行身份验证的服务器)。

Edit: you edited your question, so here's a link related to SPNEGO in Java which might be of some use: http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html 编辑:你编辑了你的问题,所以这里有一个与Java中的SPNEGO相关的链接,可能有一些用处: http//download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5 html的

You don't actually need to do anything. 你实际上不需要做任何事情。 In Java 6, on a Windows client machine you can do this: 在Java 6中,在Windows客户端计算机上,您可以执行以下操作:

new URL("http://myhost/myapp").openStream();

And negotiate authentication just works. 协商身份验证才有效。 At least it does for me. 至少它对我有用。 And the server I tested on only supports Negotiate, not NTLM auth. 我测试的服务器只支持Negotiate,而不支持NTLM auth。

Ok if you want to avoid using a login.conf file you need to code differently:- 好的,如果你想避免使用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 };
}

Now once you are done with this definition you can use this in you use this to fetch tickets from kdc 现在,一旦完成了这个定义,你可以使用它来使用它从kdc中获取票证

//get ticket in login context
LoginContext lc = null;
    lc = new LoginContext("lc", null, callback, new CustomLoginConfiguration(argumentlist));
    lc.login();

Now from here on you can fetch jaas subject and can basically do a ton of authentication stuff. 现在从这里你可以获取jaas主题,基本上可以做大量的身份验证。

In case you need further pointers just leave a comment. 如果您需要进一步的指示,请发表评论。

You can use system properties instead of config files to specify the KDC hostname and service name, but those things (at least) are mandatory.... 您可以使用系统属性而不是配置文件来指定KDC主机名和服务名称,但这些(至​​少)是强制性的....

Waffle will actually give you the information you need to set most of the properties, even if it won't get you a ticket. Waffle实际上会为您提供设置大部分房产所需的信息,即使它不会给您带票。 Look at the WindowsAuthProviderImpl class (the Waffle.chm help file shows the API). 查看WindowsAuthProviderImpl类(Waffle.chm帮助文件显示API)。

I use JAAS do obtain a service ticket from Active Directory in two steps: 我使用JAAS通过两个步骤从Active Directory获取服务票证:

  1. Use Krb5LoginModule to retrieve the cached TGT and add it to the Subject. 使用Krb5LoginModule检索缓存的TGT并将其添加到Subject。

  2. Use the Subject and GSS-API to retrieve a service ticket from the KDC. 使用Subject和GSS-API从KDC检索服务票证。

There's a lot of good information and example code at The Java Way of Active Directory . The Java Way of Active Directory中有很多好的信息和示例代码。

I created a small tool to simplify connecting with httpclient to kerberos, you might want to give it a try. 我创建了一个小工具来简化与httpclient与kerberos的连接,你可能想尝试一下。 https://github.com/DovAmir/httpclientAuthHelper 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);

这是一篇关于让一个java客户端与Kerberos一起使用的好文章http://sachithdhanushka.blogspot.com/2014/02/kerberos-java-client-configuration.html

使用WAFFLE

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM