将域名插入servlet身份验证令牌

时间:2012-08-07 20:16:16

标签: java servlets bytearray jna waffle

我在我的网络应用中使用Waffle作为SSO解决方案。

一切正常但我想稍微修改一些功能:

目前,如果用户未连接到域,则SSO会失败并打开一个小授权对话框:

enter image description here

Windows授权要求用户名称格式为Domain\Username,但我的大多数用户都不知道在用户名前添加域名。因此,如果未指定默认域名,我想提供默认域名。

我找到了一个我可以覆盖的华夫饼干功能,它可以让我访问已解码的身份验证令牌,我在waffle函数中添加了println,它以纯文本显示用户名(带或不带域名)取决于对话框中输入的内容:

public IWindowsSecurityContext acceptSecurityToken(String connectionId, byte[] token, String securityPackage) {

    // I can see the passed username in the logs with this
    System.out.println(new String(token));

    // I don't understand any of the JNA stuff below this comment:
    IWindowsCredentialsHandle serverCredential = new WindowsCredentialsHandleImpl(
            null, Sspi.SECPKG_CRED_INBOUND, securityPackage);
    serverCredential.initialize();

    SecBufferDesc pbServerToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
    SecBufferDesc pbClientToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, token);

    NativeLongByReference pfClientContextAttr = new NativeLongByReference();

    CtxtHandle continueContext = _continueContexts.get(connectionId);

    CtxtHandle phNewServerContext = new CtxtHandle();
    int rc = Secur32.INSTANCE.AcceptSecurityContext(serverCredential.getHandle(), 
            continueContext, pbClientToken, new NativeLong(Sspi.ISC_REQ_CONNECTION), 
            new NativeLong(Sspi.SECURITY_NATIVE_DREP), phNewServerContext, 
            pbServerToken, pfClientContextAttr, null);

    WindowsSecurityContextImpl sc = new WindowsSecurityContextImpl();
    sc.setCredentialsHandle(serverCredential.getHandle());
    sc.setSecurityPackage(securityPackage);
    sc.setSecurityContext(phNewServerContext);

    switch (rc)
    {
        case W32Errors.SEC_E_OK:
            // the security context received from the client was accepted
            _continueContexts.remove(connectionId);
            //  if an output token was generated by the function, it must be sent to the client process
            if (pbServerToken != null 
                    && pbServerToken.pBuffers != null
                    && pbServerToken.cBuffers.intValue() == 1 
                    && pbServerToken.pBuffers[0].cbBuffer.intValue() > 0) {
                sc.setToken(pbServerToken.getBytes());
            }
            sc.setContinue(false);
            break;
        case W32Errors.SEC_I_CONTINUE_NEEDED:
            // the server must send the output token to the client and wait for a returned token
            _continueContexts.put(connectionId, phNewServerContext);
            sc.setToken(pbServerToken.getBytes());
            sc.setContinue(true);
            break;
        default:
            sc.dispose();
            WindowsSecurityContextImpl.dispose(continueContext);
            _continueContexts.remove(connectionId);
            throw new Win32Exception(rc);
    }

    return sc;
}

整个功能来自Waffle API我只在开头添加了println。

传递的用户名在一串随机字节字符(ÉsR=ÍtÍö?æ¸+Û - )之间以明文形式打印。

我肯定在JNA和java方面已经远远超过了我的头脑但我认为因为我可以在这里看到用户名必须有一种方法将域名添加到此令牌的用户名部分?我错了。

我的另一个想法是将域添加到从此方法传递的原始byte []标记创建的pbClientToken

pbClientTokenJNA Structure object衍生物。它有Stucture方法writeField看起来很有希望,但我似乎无法弄清楚我应该写什么字段。 Structure.getFields似乎无法使用pbClientToken方法。

我希望对于更熟悉byte []处理或JNA的人来说,这是一个简单的问题。

1 个答案:

答案 0 :(得分:0)

你不能这样做。此对话框后面发生的是在用户计算机上调用LogonUser,它会为您提供票证,然后将票据发送到服务器。不幸的是,服务器不在同一个域中,所以即使你设法提取用户名,它也完全没用。