使用Java以编程方式使用不同的键表登录多个kerberos领域

使用Java以编程方式使用不同的键表登录多个kerberos领域,java,authentication,kerberos,Java,Authentication,Kerberos,出于某种原因,我的客户机需要登录到两个kerberos领域,比如REALM1和REALM2。我的委托人已在两个领域签名,并创建了两个不同的键(委托人)/host@REALM1使用keytab1和principal/host@REALM2使用键Tab2)。换言之,我可以将我的原则与两个不同的领域对立起来 现在我需要运行一个应用程序,其中首先需要在realm1中完成一些任务,然后需要在realm2中完成其他任务,因此我必须先登录realm1,完成一些工作,然后登录realm2。我试图通过在我的程序中

出于某种原因,我的客户机需要登录到两个kerberos领域,比如REALM1和REALM2。我的委托人已在两个领域签名,并创建了两个不同的键(委托人)/host@REALM1使用keytab1和principal/host@REALM2使用键Tab2)。换言之,我可以将我的原则与两个不同的领域对立起来

现在我需要运行一个应用程序,其中首先需要在realm1中完成一些任务,然后需要在realm2中完成其他任务,因此我必须先登录realm1,完成一些工作,然后登录realm2。我试图通过在我的程序中间重置系统属性“java .Security,KRB5.CONF”来完成这一操作,但是未能从RealM1切换到RealM2(登录失败,它看起来默认的状态保持不变)。
我搜索了一下,看到了相关帖子的答案(带有JAAS和多个领域的Kerberos Auth),我知道一个键表绑定到一个领域——我不明白的是——我为两个领域生成了两个键表——为什么不能登录到两个领域?只有通过跨域身份验证才能做到这一点。

不要这样做。建立跨领域信任,您可以使用客户端的原始密钥表执行外部领域中的所有任务。我们这里至少有30个领域,我的Unix机器当然是在一个领域中加入的。这很好用。

我建议您看看开源项目

查看oVirt engine的java代码,查看bll模块(oVirt engine/backend/modules/bll)中的身份验证代码(查看
DirectorySearcher.java
)-我们确实支持登录到几个kerberos领域

我们有一个名为engine manage domains的工具,允许您为域添加一个“域用户”(我们主要用于搜索添加域中的用户和组),例如:

您可以从域“example.com”中添加用户“aaa”,该域是ActiveDirectory。 这将修改在
/etc/ovirt engine/krb5.conf
中定义的、ovirt引擎使用的
krb5.conf

查看代码中创建JAAS登录对象并执行登录的位置(如果没有有效的域票证,则执行显式登录)


我也认为跨领域身份验证是更好的解决方案,但您可能会面临无法创建这种信任的情况。例如,oVirt是一个开源虚拟化管理系统,它不应该“干扰”或者强制更改用户组织中安装的其他系统的设置。

在您的情况下,您可以在每次使用之前使用JAAS login.conf中KRB5LoginModule中的refreshKrb5Config=true选项强制重新加载配置(请参阅)

但是,这在多线程应用程序中不起作用,因为您必须序列化对此共享资源的访问。javakerberos实现使用系统属性(和单个配置文件)这一事实是一个不必要的限制,甚至可能是一个bug


使用跨域信任的公认答案有时可能是好的,但并不总是好的。例如,如果您的网络管理员不希望所有服务都信任另一个域,只信任这一个特定的服务,那么您就不走运了。假设您有一个用Java编写的多线程应用程序,并且提供了一个希望接受来自多个领域的票证的服务,那么您必须在每个领域运行该应用程序的一个实例(krb5.conf hostname是静态的,只有keytab和kdc更改)。如果这个特定的应用程序是使用SPNEGO在端口443上运行的web服务,那么这将成为一个非常头痛的问题。现在,您需要在不同的端口上安装两个应用程序服务器实例?哎哟。

我来晚了,但这可能会帮助其他人在搜索中找到这个问题

使用跨领域身份验证是最好的,但并不总是可行的。例如,您可能作为受信任的第三方将数据从一个组织复制到另一个组织,并且两个组织都不向其开放

javax.security.auth.login.LoginContext类通常使用能够支持多个条目的外部配置文件。如果您的devops支持它,那么这是一种很好的方法,但在许多环境中,这是不可能的,例如,如果您在appserver上部署为.war文件。(典型示例:应用程序在AWS elastic beanstalk上自动缩放。)

在本例中,我们使用了接受配置对象的LoginContext构造函数。我们必须自己维护必要的信息,但我们可以自己处理几乎所有的事情。(我们可以下载keytab文件并将其写入临时目录,并在配置对象中指向它。请记住在应用程序退出时取消该文件!)

在本例中,有助于记住配置对象是一个包,AppConfigurationEntry是单个服务的信息


编辑以添加:您可能希望在选项中指定不同的凭据缓存文件(ccache)位置。我不记得ccache文件是否支持多个条目,但指定不同的文件不会有什么坏处。

如果它有助于其他人:

您可以在krb5.conf中指定哪些域应用于哪些域。例如:

[libdefaults]
  default_realm = A.COM

[realms]
  A.COM = {
    kdc = ...
  }
  B.COM = {
    kdc = ...
  }

[domain_realm]
  .b.com = B.COM
然后,当您连接到*.b.com时,它将使用b.com领域而不是A.com,否则默认为A.com


更多信息:

谢谢Michael,您能解释一下为什么您认为跨领域解决方案更好吗?我只是不明白:如果这些领域,以及这些任务是完全无关的呢?用两个键访问两个领域会破坏任何安全代码吗?首先,你能建立信任吗?如果是这样,这些就是好处。来自这些领域的用户可以访问任意方向的资源。您可以根据需要委派凭据