如何使用java GSS + JAAS获得可再生的kerberos票

时间:2015-04-13 17:55:47

标签: java kerberos jaas jtds jgss

我正在使用jTDS连接到SQLServer。内部jTDS使用GSS获得kerberos'服务票证并建立安全的上下文。由于我的应用程序是长寿的,我的连接一直保持活着,我需要kerberos'服务票证可以更新,以便允许SQL服务器自行续订(kdc策略设置为在12小时后使所有票证到期)。

获取kerberos令牌的jTDS所做的是(或多或少)以下内容:

GSSManager manager = GSSManager.getInstance();

// Oids for Kerberos5
Oid mech = new Oid("1.2.840.113554.1.2.2");
Oid nameType = new Oid("1.2.840.113554.1.2.2.1");

// Canonicalize hostname to create SPN like MIT Kerberos does
GSSName serverName = manager.createName("MSSQLSvc/" + host + ":" + port, nameType);

GSSContext gssContext = manager.createContext(serverName, mech, null, GSSContext.DEFAULT_LIFETIME);
gssContext.requestMutualAuth(false);
gssContext.requestCredDeleg(true);

byte[] ticket = gssContext.initSecContext(new byte[0], 0, 0);

我怀疑我获得的机票不可更新。我正在通过执行以下操作来检查:

ExtendedGSSContext extendedContext = (ExtendedGSSContext) gssContext;
boolean[] flags = (boolean[]) extendedContext.inquireSecContext(InquireType.KRB5_GET_TKT_FLAGS);
System.out.println("Renewable = " + flags[8]);

在我们的特定配置中,GSS从JAAS登录模块获取kerberos TGT。我们将以下变量设置为false -Djavax.security.auth.useSubjectCredsOnly=false,并在login.cfg文件中配置以下登录模块:

com.sun.security.jgss.krb5.initiate {
   com.sun.security.auth.module.Krb5LoginModule required
      useKeytTab=true
      keyTab="/home/batman/.batman.ktab"
      principal="batman@GOTHAMCITY.INT"
      storeKey=true
      doNotPrompt=true
      debug=false
};

我注意到的另一件事是getLifetime()的{​​{1}}方法似乎无效。无论故障单的实际生命周期是什么,它总是返回2147483647(max int)。

我对分支jTDS驱动程序感到很舒服,因此我可以根据需要修改它建立GSS上下文的方式。

我尝试了什么:

使用GSS api的原生实现:

在获取可更新票证方面,这对我来说很好,但它会产生另一组问题(在确保正确设置票证缓存和正确续订票证方面)。如果我可以绕过这个选项那就太好了。我在这里看到的一件事是GSSContext方法实际上返回了票证的实际生命周期。

重新实现KerberosLoginModule:

基于此问题的答案Jaas - Requesting Renewable Kerberos Tickets我重新实现了LoginModule,以便在请求TGT之前在getLifetime()中设置RENEW KDCOption。从我获得可再生TGT的意义上来说这很好,但GSS从TGT获得的机票仍然不可再生。如果我在KDCOption对象的构造函数中设置一个断点并在每个请求上手动设置RENEW标志(即使是GSS完成的KrbAsReqBuilder)它也能正常工作,但是要使这个变化有效,需要对GSS进行重大改写,我不会# 39;感觉很舒服。

1 个答案:

答案 0 :(得分:1)

对于管理员来说,Kerberos票证具有生命周期这一事实是一项重要的安全功能。用户知道密码,因此他/她可以随时获得新票。但是对于入侵者来说这是一个问题 - 在票证到期后,它不能用于进入系统。管理员希望这个生命周期尽可能短,但不要太短(比如1小时),因为用户生成的登录请求比现在多10倍,而且ActiveDirectory很难处理。

当我们需要使用Kerberos进行身份验证时,我们应该使用连接池(和DataSource)。要在jTDS中使用此功能,您需要添加ConnectionPoolImplementation(建议:DBCP或c3p0,请参阅:http://jtds.sourceforge.net/features.html)。

如果您想使用较旧的连接数据库的方式编写应用程序(没有数据源,即创建连接并保持活动,因为创建它很昂贵......),那么下一个障碍就是“更新生命周期”。在ActiveDirectory中,默认情况下,Kerberos票证可在7天内续订。 AD中有一个全局设置允许设置为0(无限期更新生命周期),但是你需要说服域管理员降低整个域的安全性,因为一个服务在没有它的情况下就不会运行。