我正在以编程方式尝试使用Java中的Waffle创建SPNEGO令牌,因此我可以验证与Kerberos和Windows AD集成的Web服务器,而不必强制用户再次登录。客户端计算机是Windows 10 Professional机器。
代码本身运行正常,没有错误-它正在生成令牌,但是该令牌在服务器端的验证失败:
[12/4/19 12:37:42:637 CST] 00006691 Context E
com.ibm.ws.security.spnego.Context begin CWSPN0011E: A non-valid SPNEGO token has been encountered while authenticating a HttpServletRequest: 0000:
a1143012 a0030a01 01a10b06 092a8648
..0. .... .... .*.H
0010: 82f71201 0202 .... ..
当然,在客户端,我得到的是403。Java代码是从命令行运行的,还是现在运行的。在进行下一步之前,我想使此工作正常。创建令牌的代码是:
public static byte[] getServiceTicketSSPI() {
final String securityPackage = "Kerberos";
final String targetName = "HTTP/...com@...COM";
IWindowsCredentialsHandle clientCredentials = null;
WindowsSecurityContextImpl clientContext = null;
final String currentUser = WindowsAccountImpl.getCurrentUsername();
try {
clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage);
clientCredentials.initialize();
// initial client security context
clientContext = new WindowsSecurityContextImpl();
clientContext.setPrincipalName(currentUser);
clientContext.setCredentialsHandle(clientCredentials);
clientContext.setSecurityPackage(securityPackage);
final Sspi.SecBufferDesc continueToken = null;
do {
System.out.println("Using target name: " + targetName);
clientContext.initialize(clientContext.getHandle(), continueToken, targetName);
} while(clientContext.isContinue());
return clientContext.getToken();
} finally {
if (clientContext != null)
clientContext.dispose();
if (clientCredentials != null)
clientCredentials.dispose();
}
}
令牌本身的长度为2512个字节(经过Base64编码后):
YIIHVgY....auD980gy5w==
最后是将其添加到请求标头的代码。我尝试了2种不同的方式,都返回403:
1st way:
HttpGet request = new HttpGet(args[0]);
String authHeader = "Negotiate " + Base64.getUrlEncoder().encodeToString(clientToken);
request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
System.out.println(statusCode);
2nd way:
URL url = new URL(args[0]);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// insert SPNEGO token in the HTTP header
con.setRequestProperty("Authorization", "Negotiate " + Base64.getUrlEncoder().encodeToString(clientToken));
con.getResponseCode();
InputStream ins = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
String str;
while((str = reader.readLine()) != null)
System.out.println(str);
是否有关于如何在对令牌进行编码或将其分配给HTTP请求之前验证令牌的想法?我不确定如何调试此错误,因为客户端代码正在处理错误。我无权访问服务器或服务器日志,但是可以向管理员提出请求。
谢谢。