Java Waffle创建无效的SPNEGO令牌

时间:2019-12-05 01:35:32

标签: java kerberos spnego waffle

我正在以编程方式尝试使用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请求之前验证令牌的想法?我不确定如何调试此错误,因为客户端代码正在处理错误。我无权访问服务器或服务器日志,但是可以向管理员提出请求。

谢谢。

0 个答案:

没有答案