0

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

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

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

在此处输入图像描述

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

我找到了一个可以覆盖的 waffle 函数,它可以让我访问解码的身份验证令牌,我println在 waffle 函数中添加了一个,它以纯文本形式显示用户名(有或没有域,具体取决于在对话框中键入的内容) ):

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 的理解非常遥远,但我认为因为我可以在这里看到用户名,所以必须有一种方法可以将域名添加到此令牌的用户名部分?我可能是错的。

我的另一个想法是将域添加到pbClientToken从传递此方法的原始字节 [] 令牌创建的域中。

JNA对象派生类pbClientToken。它的方法看起来很有希望,但我似乎无法弄清楚我应该写什么领域。该方法似乎不适用于.StructureStucturewriteFieldStructure.getFieldspbClientToken

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

4

1 回答 1

1

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

于 2013-02-21T05:25:37.730 回答