java - 如何使用java GSS+JAAS获取可更新的kerberos票据

标签 java kerberos jaas jtds jgss

我正在使用 jTDS 连接到 SQLServer。 jTDS 在内部使用 GSS 获取 kerberos 的服务票证并建立安全上下文。由于我的应用程序生命周期很长并且我的连接一直保持 Activity 状态我需要 kerberos 的服务票证是可更新的,以允许 SQL 服务器自行更新它们(kdc 策略设置为在 12 小时后过期所有票证).

jTDS 为获取 kerberos token 所做的(或多或少)如下:

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
};

我注意到的另一件事是 GSSContextgetLifetime() 方法似乎不起作用。它总是返回 2147483647 (max int) 无论票的实际生命周期是多少。

我觉得分支 jTDS 驱动程序很舒服,所以我可以根据需要修改它建立 GSS 上下文的方式。

我尝试了什么:

使用 GSS api 的 native 实现:

这在获取可更新票证方面对我来说很好,但它带来了另一组问题(在确保正确设置票证缓存和正确更新其中的票证方面)。如果我能绕过这个选项就好了。我在这里观察到的一件事是 getLifetime() 方法实际上返回了票证的真实生命周期(以秒为单位)。

重新实现 KerberosLoginModule:

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

最佳答案

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

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

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

关于java - 如何使用java GSS+JAAS获取可更新的kerberos票据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29611871/

相关文章:

java - 如何为 WebSphere 上的远程 EJB 调用启用 Kerberos 身份验证?

asp.net 通过 kerberos 集成 windows 身份验证到 sql server

java - 了解和探索 JAAS-GSSAPI-JNDI 如何在后台协同工作

Java 阶乘输出

java - Selenium 脚本在 jenkins 中失败,但在本地运行良好

java - 编写并发代码、非阻塞代码

authentication - Hadoop 身份验证 http-signature.secret 文件

jsf-2 - 登录失败 : javax. security.auth.login.FailedLoginException: 密码不正确/需要密码

jsf - 记录器,从@Inject 转换为生产者

java - 在每个事务中查询\更新数据库是否有效 : Java Application