使用Java中的Waffle获取Kerberos服务票证

时间:2018-04-24 15:56:57

标签: java single-sign-on kerberos sspi waffle

我正在使用在Windows 10上运行的Java应用程序中的真正SSO。我的应用程序已经使用Java的GSSAPI进行了Kerberos身份验证(但它显然无法在任何现代Windows上运行,特别是对于严格的安全策略和域用户),所以我我想用Waffle替换当前的授权系统,对整体应用程序设计的影响很小 - 如果我能以某种方式得到KerberosTicket实例,我认为这应该是可能的。我正在努力编写这个功能,到目前为止我设法请求一些令牌,但我真的不知道这个令牌是什么,它与Kerberos票证格式不匹配。这是我的(实际上更像在线代码):

public byte[] getServiceTicketSSPI() {
    final String securityPackage = "Kerberos";
    final String targetName = "<disclosed>";
    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 {
            if(debug)
                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();
    }
}

公平地说,我甚至不确定SSPI是否允许我真正看到真正的票。我甚至用这个片段朝着正确的方向前进?我会很高兴,所以看看我应该做些什么的线索。最终拥有KerberosTicket实例是完美的。

1 个答案:

答案 0 :(得分:0)

下面是在不使用服务器的情况下使用Waffle for独立Java Client进行单点登录的步骤。

创建客户端凭据 使用WindowsSecurityContextImpl的initializeSecurityContext获取服务票证。 使用WindowsAuthProviderImpl的accessSecurityContext获取WindowsIdentity 原始链接https://exceptionshub.com/getting-kerberos-service-ticket-using-waffle-in-java.html

对于客户端-服务器sso,您应遵循https://code.dblock.org/2010/04/08/pure-java-waffle.html,以下代码描述了使用kerberos的独立java sso。

import com.sun.jna.platform.win32.Sspi;
import waffle.windows.auth.IWindowsCredentialsHandle;
import waffle.windows.auth.IWindowsIdentity;
import waffle.windows.auth.IWindowsSecurityContext;
import waffle.windows.auth.impl.WindowsAccountImpl;
import waffle.windows.auth.impl.WindowsAuthProviderImpl;
import waffle.windows.auth.impl.WindowsCredentialsHandleImpl;
import waffle.windows.auth.impl.WindowsSecurityContextImpl;

public class KerberosSingleSignOn {
  public static void main() {
    try {
      System.out.println(getWindowsIdentity().getFqn());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static IWindowsIdentity getWindowsIdentity() throws Exception {
    try {
      byte[] kerberosToken = getServiceTicketSSPI();
      WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
      IWindowsSecurityContext securityContext = provider
        .acceptSecurityToken("client-connection", kerberosToken, "Kerberos");
      return securityContext.getIdentity();
    }
    catch (Exception e) {
      throw new Exception("Failed to process kerberos token");
    }
  }

  public static byte[] getServiceTicketSSPI() throws Exception {
    final String securityPackage = "Kerberos";
    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.setCredentialsHandle(clientCredentials.getHandle());
      /*OR 
       clientContext.setCredentialsHandle(clientCredentials);
       */
      clientContext.setSecurityPackage(securityPackage);
      final Sspi.SecBufferDesc continueToken = null;
      do {
        System.out.println("Using current username: " + currentUser);
        clientContext.initialize(clientContext.getHandle(), continueToken, currentUser);
      }
      while (clientContext.isContinue());

      return clientContext.getToken();
    }
    catch (Exception e) {
      throw new Exception("Failed to process kerberos token");
    }
    finally {
      if (clientContext != null)
        clientContext.dispose();
      if (clientCredentials != null)
        clientCredentials.dispose();
    }
  }
}