【问题标题】:Kerberos broken after upgrading from Java6 to Java7从 Java 6 升级到 Java 7 后 Kerberos 损坏
【发布时间】:2012-11-28 00:20:44
【问题描述】:

我有一个使用 spring-security kerberos 扩展的工作应用程序,在 jboss 上运行,运行 java 6。

我正在将我的 jvm 从 java 6 升级到 java 7。当我这样做时,使用在 java 6 上工作的相同代码库和相同的 keytab,我现在在使用 java 7 时收到一个错误。

我一直收到: java.security.PrivilegedActionException:GSSException:在 GSS-API 级别未指定失败 (机制级别:无效参数(400)- 找不到合适类型的密钥来解密 AP REP - RC4 with HMAC)

我尝试使用其他论坛中描述的不同 /crypto 选项重新生成密钥表,但无济于事。

我已经调试了 java 7 代码,实际上,处理启动时读取 keytab 的类从 6 更改为 7。难道我的 keytab 没有被正确读入应用程序了吗?我在使用 Java6 启动时看到的一些调试消息在 7 中不再出现,但我不知道这是设计使然,还是表明还有其他东西在起作用?有没有其他人在从 6 升级到 7 时遇到问题,并且他们的 kerberos 集成中断了?有什么建议吗?

在启动时登录 spnego 和 kerberos 调试,我的日志显示:

2012-12-10 10:29:30,886  Debug is  true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is jndi:/localhost/docfinity/WEB-INF/classes/config/common/security/http-docfinity.keytab refreshKrb5Config is false principal is HTTP/VMMSSDEV.TESTING.LOCAL@TESTING.LOCAL tryFirstPass is false useFirstPass is false storePass is false clearPass is false
2012-12-10 10:30:26,322  principal is HTTP/VMMSSDEV.TESTING.LOCAL@TESTING.LOCAL
2012-12-10 10:30:29,794  Will use keytab
2012-12-10 10:30:29,807  Ordering keys wrt default_tkt_enctypes list
2012-12-10 10:30:29,821  Config name: C:\Windows\krb5.ini
2012-12-10 10:30:29,827  Using builtin default etypes for default_tkt_enctypes
2012-12-10 10:30:29,832  default etypes for default_tkt_enctypes:
2012-12-10 10:30:29,837   17    aes128-cts-hmac-sha1-96
2012-12-10 10:30:29,839   16    des3-cbc-sha1-kd
2012-12-10 10:30:29,842   23    rc4-hmac
2012-12-10 10:30:29,846   1     des-cbc-crc
2012-12-10 10:30:29,849   3     des-cbc-md5
2012-12-10 10:30:29,851  .
2012-12-10 10:30:29,855  Commit Succeeded 

另一个问题 - 您会看到它正在尝试读取 C:\Windows\krb5.ini。我的服务器上没有这样的文件。我需要一个吗?我也没有使用 java 6 的,但它有效。

亚伦

【问题讨论】:

  • 你的 keytab 支持什么加密?这一定是问题所在。 JGSS 支持列出的 etype,但您的 keytab 需要 ArcFour 才能响应 AS。
  • 您是在问我在生成密钥表时使用了什么 /crypto 吗?如果这是问题所在,那么我已经尝试了很多——专门指定 RC4-HMAC 并使用 ALL 选项。我不确定你问的是什么,是吗?
  • 是的,这正是我的问题。您是否启用了-Dsun.security.krb5.debug=true 以查看 Kerberos 调试输出?
  • Michael - 首先,感谢您的帮助 - 我需要它。啊。其次,我启用了 debug=true 设置。有什么我可以提供的东西可以给你任何见解吗?原始消息中的 sn-p 是我在启动时看到的。你也想要一些我在身份验证期间看到的日志吗?
  • 您确实启用了LoginModule,但并未启用所有与 Kerberos 相关的类。这是一个区别。将该环境属性添加到您的 JBOss 启动环境中。

标签: spring-security java-7 kerberos java-6 spnego


【解决方案1】:

是的!我们对 SunJaasKerberosTicketValidator 进行了修补,使其看起来像这样,并且它起作用了:

String keyTabPath = this.keyTabLocation.getURL().toExternalForm();
String runtimeVersion = System.getProperty("java.version");
if (runtimeVersion.startsWith("1.7")) 
{
      LOG.info("Detected jdk 7. Modifying keytabpath");
      if (keyTabPath != null)
      {
        if (keyTabPath.startsWith("file:")) 
        {
            keyTabPath = keyTabPath.substring(5);
        }
      }
}
LOG.info("KeyTabPath: " + keyTabPath);
LoginConfig loginConfig = new LoginConfig(keyTabPath, this.servicePrincipal,
                this.debug);

【讨论】:

    【解决方案2】:

    以下是两个可能影响您的潜在问题:

    1. Java 7 似乎切换了默认的加密类型顺序。详情:

    2. 您没有说明您使用的是哪个特定版本的 JDK 7,但早期版本的 JDK 7 中存在一个错误,该错误会阻止通过“file:”URL 加载 keytab 文件:

    SO 上的另一个用户通过修改 Spring 源解决了最后一个问题:

    【讨论】:

      【解决方案3】:

      将 keyTabLocation 对象更改为字符串。

      So private String keyTabLocaiton.
      
            @Override
              public void afterPropertiesSet() throws Exception {
                  Assert.notNull(this.servicePrincipal, "servicePrincipal must be specified");
                  Assert.notNull(this.keyTabLocation, "keyTab must be specified");
                  // if (keyTabLocation instanceof ClassPathResource) {
                  // LOG.warn("Your keytab is in the classpath. This file needs special protection and shouldn't be in the classpath. JAAS may also not be able to load this file from classpath.");
                  // }
                  LoginConfig loginConfig = new LoginConfig(this.keyTabLocation, this.servicePrincipal,
                          this.debug);
                  Set<Principal> princ = new HashSet<Principal>(1);
                  princ.add(new KerberosPrincipal(this.servicePrincipal));
                  Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
                  LoginContext lc = new LoginContext("", sub, null, loginConfig);
                  lc.login();
                  this.serviceSubject = lc.getSubject();
              }
      

      同样在 LoginConfig 的地方,将 isInitiator 标志设置为 true。

       public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
                  HashMap<String, String> options = new HashMap<String, String>();
                  options.put("useKeyTab", "true");
                  options.put("keyTab", this.keyTabLocation);
                  options.put("principal", this.servicePrincipalName);
                  options.put("storeKey", "true");
                  options.put("doNotPrompt", "true");
                  if (this.debug) {
                      options.put("debug", "true");
                  }
                  options.put("isInitiator", "true");
                  //options.put("isInitiator", "false");
      
                  return new AppConfigurationEntry[] { new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
                          AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), };
              }
      

      希望这可以帮助您解决问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-19
        • 2012-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多