【发布时间】:2016-07-17 05:04:06
【问题描述】:
我编写了一个在 Windows 下运行的简单 Java HTTP 客户端。客户端与需要通过 SPNego 进行 Kerberos 身份验证的 Web 服务器通信。
我遇到了两个问题:
服务票证未存储在我的凭据缓存中。执行请求后,我希望看到一个 Kerberos 服务票证存储在我的凭据缓存中
C:\Users\<user>\krb5cc_<user>下 - 我假设 Java 将服务票证存储在凭据缓存中是错误的吗?我想重用在客户端 A 中获得的服务票证用于客户端 B 中的请求(其中两个客户端都是同一台机器上的 Java 应用程序)。 Java可以做到吗?如果我在循环中运行代码低于一百次,它只能工作 n 次(其中 n 是 1 到 100 之间的随机数)。失败的请求返回 401 错误消息,因为 Java 无法检索服务票证(请记住:由于我的应用程序不会在请求之间存储服务票证,它会尝试从 TGT 为每个请求获取新的服务票证) .我已将错误消息添加到此问题的底部。
我已经通过 kinit 在我的 JDK 的 bin 文件夹中创建了一个 TGT。以下代码 sn -p 用于发出简单的 GET 请求:
static void testJavaHttpKerberosAuthentication() throws IOException {
URL obj = new URL(URI);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + URI);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
}
这是我的 jaas.conf 的内容(如 here 所述):
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required doNotPrompt=false useTicketCache=true;
};
我正在使用以下参数运行我的应用程序:
-Djava.security.auth.login.config=D:\jaas.conf
-Dsun.security.krb5.debug=true
-Djavax.security.auth.useSubjectCredsOnly=false
我没有使用 krb5.ini,因为我的客户端从域配置中获取了正确的 KDC。
我可以通过以下命令为我的凭据缓存生成 TGT:
C:\Program Files\Java\jdk1.8.0_77\bin>kinit
Password for <user>@<domain>:
New ticket is stored in cache file C:\Users\<user>\krb5cc_<user>
最后,这里是授权失败情况下的异常和 Kerberos 调试输出(参考问题 2)。请注意,ctime 显然是错误的。我进行了许多不同的尝试,ctime 的时间跨度从 1970 年到 2040 年不等。有趣的是,并非每个请求都会发生这种情况。
>>>KRBError:
cTime is Wed Jun 07 12:24:03 CEST 2017 1496831043000
sTime is Tue Mar 29 16:38:24 CEST 2016 1459262304000
suSec is 283371
error code is 34
error Message is Request is a replay
sname is HTTP/<spn>@<domain>
msgType is 30
KrbException: Request is a replay (34) - PROCESS_TGS
我已经尝试使用Subject.doAs 与 JAAS 一起工作,但这会导致同样的问题。通过浏览器访问服务器可以正常工作(尽管这无法比较,因为浏览器使用的是 Windows 本机凭据缓存 AFAICT)。
如果您能提供一些关于如何调试此类问题的建议,我将不胜感激。
编辑:通过KRB5CCNAME 环境变量明确指定凭证缓存的路径,不会改变行为。似乎 TGT 是从凭据缓存中获取的,但服务票证并未存储在那里。
【问题讨论】:
-
顺便说一句,有两个额外的跟踪标志可以证明是有用的:
-Djava.security.debug=gssloginconfig,configfile,configparser,logincontext用于调试 JAAS 配置问题,当然还有-Dsun.security.spnego.debug=true
标签: java authentication kerberos jaas