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

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

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



Windows授权要求使用类似于Domain\Username格式的用户名,但是我的大多数用户都不知道将域添加到用户名之前。因此,如果未指定默认域名,我想提供一个默认域名。

我找到了一个可以覆盖的waffle函数,它将使我能够访问已解码的身份验证令牌,我在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的人来说,这是一个简单的问题。

最佳答案

你不可以做这个。在此对话框后面发生的是在用户计算机上调用LogonUser的操作,该操作会给您一张票证,然后将其发送到服务器。不幸的是,服务器不在同一域中,因此即使您设法提取用户名,它也完全没有用。

关于java - 将域名插入servlet身份验证 token ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11853433/

10-11 07:54