【问题标题】:Call to GSSContext.initSecContext fails intermittently: Receive timed out对 GSSContext.initSecContext 的调用间歇性失败:接收超时
【发布时间】:2013-03-19 14:02:43
【问题描述】:

我正在使用服务编写用于 Windows Kerberos 身份验证的客户端代码(省略日志记录代码):

System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
// System.setProperty("sun.security.krb5.debug", "true");
Package thisPkg = AuthHelper.class.getPackage();
String configPath = Util.getConfigPath(thisPkg, "jaas.conf");
System.setProperty("java.security.auth.login.config", "=" + configPath);
GSSManager manager = GSSManager.getInstance();
GSSName peerName = manager.createName(spn, GSSName.NT_HOSTBASED_SERVICE);
GSSContext context = manager.createContext(peerName, null, null,
    GSSContext.DEFAULT_LIFETIME);
context.requestMutualAuth(true); // required
context.requestCredDeleg(true); // required for publish
byte[] serverTokenBytes = new byte[0];
while (!context.isEstablished()) {
  byte[] clientTokenBytes = context.initSecContext(serverTokenBytes, 0,
      serverTokenBytes.length);
  if (clientTokenBytes != null)
    socket.send(createClientMessage(clientTokenBytes));
  if (context.isEstablished()) break;
  Message message = socket.receive();
  String serverToken = message.getFirst("SERVERTOKEN").toString();
  serverTokenBytes = Base64.decodeBase64(serverToken);
}

jaas.conf 仅包含:

sp {
  com.sun.security.auth.module.Krb5LoginModule required debug=true;
};

我还根据需要设置了allowtgtsessionkey注册表项,并安装了JCE Unlimited Strength Jurisdiction Policy Files 7

代码有时有效(即建立了相互身份验证);但是,有时它会在第一次调用 GSSContext.initSecContext 时卡住一段时间,大约一分钟后抛出异常:

Exception in thread "main" GSSException: No valid credentials provided (Mechanism level: Receive timed out)
  ...
Caused by: java.net.SocketTimeoutException: Receive timed out
  ...

当我启用 Kerberos 调试输出时(通过取消上面第二行的注释),我可以看到协议有时会卡在以下行:

getKDCFromDNS using UDP

A Java Kerberos troubleshooting website 表明这是 Kerberos 身份验证服务器的问题,但我知道该服务器已启动并正在运行,因为我们有类似的 C# 代码(使用 .NET 库)编写,永远不会卡住。

【问题讨论】:

    标签: java authentication configuration windows-authentication kerberos


    【解决方案1】:

    Kerberos 身份验证服务器的 DNS 解析似乎正在通过某种间接方式,这是不可靠的。如果您明确指定服务器(在代码开头的某处),它将绕过该重定向:

    System.setProperty("java.security.krb5.realm", "<YOUR_KRB_REALM>");
    System.setProperty("java.security.krb5.kdc", "<YOUR_KRB_SERVER_ADDR_OR_IP>");
    

    编辑:事实证明,由于使用 UDP 的协议,与 Kerberos 服务器的通信本质上是不可靠的,因此对于相对较远的服务器来说,它很有可能失败。 Windows 8 默认使用 TCP;在以前的版本上强制 TCP

    • XP/2000:在HKLM\System\CurrentControlSet\Control\Lsa\Kerberos 中,将DWORD MaxPacketSize 设置为1
    • 2003/Vista/7:在HKLM\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters 中,将DWORD MaxPacketSize 设置为1

    (请注意,相同的注册表目录还需要将 DWORD AllowTGTSessionKey 设置为 1 才能使 Kerberos 正常工作。)

    【讨论】:

    • 如果您,您的管理员必须修复 DNS。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 2019-04-18
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    相关资源
    最近更新 更多