Java 对GSSContext.initSecContext的调用间歇性失败:接收超时

Java 对GSSContext.initSecContext的调用间歇性失败:接收超时,java,authentication,configuration,windows-authentication,kerberos,Java,Authentication,Configuration,Windows Authentication,Kerberos,我正在使用服务为Windows Kerberos身份验证编写客户端代码(省略日志代码): System.setProperty(“javax.security.auth.UseSubjectCredOnly”、“false”); //set属性(“sun.security.krb5.debug”、“true”); Package thisPkg=AuthHelper.class.getPackage(); 字符串configPath=Util.getConfigPath(thisPkg,“jaa

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

System.setProperty(“javax.security.auth.UseSubjectCredOnly”、“false”);
//set属性(“sun.security.krb5.debug”、“true”);
Package thisPkg=AuthHelper.class.getPackage();
字符串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\u基于主机的\u服务);
GSSContext context=manager.createContext(peerName,null,null,
GSSContext.DEFAULT_生存期);
context.requestMutualAuth(true);//必修的
context.requestCredDeleg(true);//需要发布
字节[]serverTokenBytes=新字节[0];
而(!context.isEstablished()){
byte[]clientTokenBytes=context.initSecContext(serverTokenBytes,0,
serverTokenBytes.length);
if(clientTokenBytes!=null)
send(createClientMessage(clientTokenBytes));
if(context.isEstablished())中断;
Message=socket.receive();
字符串serverToken=message.getFirst(“serverToken”).toString();
serverTokenBytes=Base64.decodeBase64(serverToken);
}
其中
jaas.conf
仅包含:

sp{
com.sun.security.auth.module.Krb5LoginModule required debug=true;
};
我还根据需要设置并安装了
allowtgsessionkey
注册表项

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

线程“main”gssexException中的异常:未提供有效凭据(机制级别:接收超时) ... 原因:java.net.SocketTimeoutException:接收超时 ... 当我启用Kerberos调试输出时(通过取消上面第二行的注释),我可以看到协议有时会卡在第行:

getKDCFromDNS using UDP

这表明这是Kerberos身份验证服务器的问题,但我知道服务器已启动并正在运行,因为我们使用C#(使用.NET库)编写了类似的代码,这些代码从未被卡住。

Kerberos身份验证服务器的DNS解析似乎正在经历某种间接过程,这是不可靠的。如果显式指定服务器(代码开头的某个位置),它将绕过该重定向:

System.setProperty(“java.security.krb5.realm”,”);
setProperty(“java.security.krb5.kdc”,”;
编辑:事实证明,由于使用UDP的协议,与Kerberos服务器的通信本质上是不可靠的,因此对于相对较远的服务器,它很有可能失败。Windows8默认使用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
allowgtsessionkey
设置为
1
,Kerberos才能正常工作。)

Kerberos身份验证服务器的DNS解析似乎正在经历某种间接过程,这是不可靠的。如果显式指定服务器(代码开头的某个位置),它将绕过该重定向:

System.setProperty(“java.security.krb5.realm”,”);
setProperty(“java.security.krb5.kdc”,”;
编辑:事实证明,由于使用UDP的协议,与Kerberos服务器的通信本质上是不可靠的,因此对于相对较远的服务器,它很有可能失败。Windows8默认使用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
allowgtsessionkey
设置为
1
,Kerberos才能正常工作。)

如果是,管理员必须修复DNS。如果是,管理员必须修复DNS。