3

我有一个使用 SSO 的站点,它使用 NTLM 身份验证,到目前为止它在 XP 和 win 7(32 位)上运行良好,但最近我的公司决定也使用 win 7(64 位)计算机。在这些PC上,握手在type 2消息后结束,tomcat返回401。我不知道如何调查,也许这里有人可以给我一些提示。

这是在 servlet 的 doPost 方法中:

        try {
        // NTLM Handshake
        // 1: Client --> Server | GET ...
        // 2: Client <-- Server | 401 Unauthorized/WWW-Authenticate: NTLM

        String auth = request.getHeader("Authorization");
        if (auth == null) {
            response.setStatus(response.SC_UNAUTHORIZED);
            response.setHeader("WWW-Authenticate", "NTLM");
            response.flushBuffer();
            return;
        }
        if (auth.startsWith("NTLM ")) {
            byte[] msg = new sun.misc.BASE64Decoder().decodeBuffer(auth
                    .substring(5));
            int off = 0, length, offset;

            // 3: Client --> Server | GET .../Authorization: NTLM
            // <base64-encoded type-1-message>
            if (msg[8] == 1) {
                // 4: Client <-- Server | 401 Unauthorized/WWW-Authenticate:
                // NTLM <base64-encoded type-2-message>
                byte z = 0;
                byte[] msg1 = { (byte) 'N', (byte) 'T', (byte) 'L',
                        (byte) 'M', (byte) 'S', (byte) 'S', (byte) 'P', z,
                        (byte) 2, z, z, z, z, z, z, z, (byte) 40, z, z, z,
                        (byte) 1, (byte) 130, z, z, z, (byte) 2, (byte) 2,
                        (byte) 2, z, z, z, z, z, z, z, z, z, z, z, z };

                response.setHeader("WWW-Authenticate", "NTLM "
                        + new sun.misc.BASE64Encoder().encodeBuffer(msg1));
                //response.sendError(response.SC_UNAUTHORIZED);
                response.setStatus(response.SC_UNAUTHORIZED);
                response.flushBuffer();
                return;
            }
            // 5: Client --> Server | GET .../Authorization: NTLM
            // <base64-encoded type-3-message>
            else if (msg[8] == 3) {
                off = 30;

                length = msg[off + 17] * 256 + msg[off + 16];
                offset = msg[off + 19] * 256 + msg[off + 18];
                String remoteHost = new String(msg, offset, length);

                length = msg[off + 1] * 256 + msg[off];
                offset = msg[off + 3] * 256 + msg[off + 2];
                String domain = new String(msg, offset, length);

                for (int i = 0; i < domain.length(); i += 2)
                    loginDomain += domain.charAt(i);

                length = msg[off + 9] * 256 + msg[off + 8];
                offset = msg[off + 11] * 256 + msg[off + 10];
                String username = new String(msg, offset, length);

                for (int i = 0; i < username.length(); i += 2)
                    loginUser += username.charAt(i);
            }
        }
    } catch (Exception se) {
        log.error(loginUser + ", NTLM handshake exception:", se);
    }
4

4 回答 4

5

尝试这个

使用以下代码启用 NTLM 扩展安全性

byte[] msg1 = {
  (byte) 'N', (byte) 'T', (byte) 'L', (byte) 'M',
  (byte) 'S', (byte) 'S', (byte) 'P',
  z, (byte) 2, z, z, z, z, z, z, z, (byte) 40, z, z, z,
  (byte) 1, (byte) 130, **(byte) 8**, z, z, (byte) 2, (byte) 2,
  (byte) 2, z, z, z, z, z, z, z, z, z, z, z, z 
};
于 2016-02-18T11:41:21.723 回答
2

这是 64 位 PC 上的一个政策问题,因为 NTLMv2 是强制的。解决方案是在安全策略中禁用这些设置。

• 运行“secpol.msc” 这应该会打开一个标题为“本地安全策略”的窗口

• 安全设置 > 本地策略 > 安全选项 > “网络安全:基于 NTLM SSP 的最低会话安全……”

有两个类似的条目以这样开头,打开并取消选中“需要 NTLMv2 会话安全”。

至少事实证明我们使用的是 NTLMv1。:|

于 2013-05-14T14:21:40.937 回答
1

如果您仍然想坚持使用 JCIFS,请尝试使用这些链接来克服“无效参数错误”和“无法与合适的域控制器协商”。它适用于 NTLM,但不能保证更安全地使用 NTLMv2。

“无效参数” https://www.sysaid.com/Sysforums/posts/list/9065.page

“未能与合适的域控制器协商” https://lists.samba.org/archive/jcifs/2005-August/005312.html

于 2015-07-02T16:18:23.593 回答
0

大多数企业网络将迁移到 NTLMv2。我们前段时间遇到了这个问题,并从http://www.ioplex.com/获得了 Jespa 。只要您有一个 Servlet 堆栈,它就可以正常工作。如果您使用的是像 Play 这样的非 Java EE 堆栈,我不知道除了拒绝对 NTLMv1 的支持之外的解决方案。

于 2013-08-21T21:34:04.980 回答