问题 在Java应用程序中使用NTLM身份验证


我想在我的Java应用程序中使用Windows NTLM身份验证来透明地验证Intranet用户。如果使用浏览器(单点登录),用户不应注意任何身份验证。

我找到了一些支持NTLM的库,但不知道使用哪一个:

有什么建议从哪里开始?


8472
2018-02-22 09:25


起源

另请注意,在使用NTLM进行身份验证时,主动攻击者可以 验证自己的会话 使用有效用户与服务器的协商。 - Michael


答案:


在上面的列表中,只有ntlmv2-auth和Jespa支持NTLMv2。 Jespa可行但商业化。 ntlmv2-auth我没有尝试,但它基于Liferay的代码,我以前见过它。

'ntlm-authentication-in-java'只是NTLMv1,它是旧的,不安全的,并且随着人们升级到更新的Windows版本而在不断减少的环境中工作。 JCIFS曾经有一个NTLMv1 HTTP身份验证过滤器,但它在以后的版本中被删除,因为它的实现方式相当于对不安全协议的中间人攻击。 (“ntlm-authentication-in-java”的情况也是如此。)

'spnego'项目是Kerberos而不是NTLM。如果你想要像IIS那样复制完整的IWA,你需要同时支持NTLMv2和Kerberos('NTLM'auth,'Negotiate'auth,NTLMSSP-in-SPNego auth和NTLM-masquerading-as-Negotiate auth)。


10
2018-02-22 16:04



Waffle也是仅适用于WIndows服务器的一个非常好的选择,已经使用了3年,在多个站点上有数千次登录没有问题,支持v2 - Tony BenBrahim
jcifs.samba.org/src/docs/faq.html#ntlmv2    >问:jCIFS是否支持NTLMv2? > A:是的。从1.3.0开始,JCIFS完全支持NTLMv2并默认使用它 Note: The NTLM HTTP SSO Filter that used to be included with JCIFS cannot support NTLMv2. - Nikhil


Luigi Dragone的剧本很老,似乎总是失败。

如果添加库,HttpURLConnection可以与NTLM一起使用 JCIFS,这个例子适用于最新版本 JCIFS-1.3.18 :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.impl.auth.NTLMEngineException;

public class TestNTLMConnection {
    public static void main(String[] args) throws UnknownHostException, IOException, NTLMEngineException {
        // Method 1 : authentication in URL
        jcifs.Config.registerSmbURLHandler();
        URL urlRequest = new URL("http://domain%5Cuser:pass@127.0.0.1/");

        // or Method 2 : authentication via System.setProperty()
        // System.setProperty("http.auth.ntlm.domain", "domain");
        // System.setProperty("jcifs.smb.client.domain", "domain");
        // System.setProperty("jcifs.smb.client.username", "user");
        // System.setProperty("jcifs.smb.client.password", "pass");
        // Not verified // System.setProperty("jcifs.netbios.hostname", "host");
        // System.setProperty("java.protocol.handler.pkgs", "jcifs");
        // URL urlRequest = new URL("http://127.0.0.1:8180/simulate_get.php");

        HttpURLConnection conn = (HttpURLConnection) urlRequest.openConnection();

        StringBuilder response = new StringBuilder();

        try {
            InputStream stream = conn.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(stream));

            String str = "";
            while ((str = in.readLine()) != null) {
                response.append(str);
            }
            in.close();   

            System.out.println(response);
        } catch(IOException err) {
            System.out.println(err);
        } finally {
            Map<String, String> msgResponse = new HashMap<String, String>();

            for (int i = 0;; i++) {
                String headerName = conn.getHeaderFieldKey(i);
                String headerValue = conn.getHeaderField(i);
                if (headerName == null && headerValue == null) {
                    break;
                }
                msgResponse.put(headerName == null ? "Method" : headerName, headerValue);
            }

            System.out.println(msgResponse);
        }
    }
}

如果你对每次握手的内容感到好奇,你可以在这里找到另一个使用jcifs和Socket的例子 线


3
2017-12-16 20:14



你能否更清楚地说明这个URL部分,我的意思是如何传递用户名和密码 - Sony
%5C是反斜杠。例如h-t-t-p:// CORP \ username:password@127.0.0.1/ - ron190
第一种方法给了我复杂网址的问题,但注释掉的方法2在Windows Server 2012上使用Java 1.7和jcifs 1.3.17对IIS运行良好。 - rwheadon


相对于你给出的清单,我会选择 JCIFS。 图书馆很成熟,文档很好。 最重要的是他们有相当规律的发布,最后一个是2011年11月。

Personal Experience :与我尝试过的其他人相比,它很容易上手(spnego和ntmv2auth)


0
2018-02-22 09:41



JCIFS不支持NTLMv2(即Windows 7/8),除非通过全局策略或注册表更改在客户端计算机上明确启用。 - Tony BenBrahim
你能澄清一下Windows 7/8中显式设置的含义吗? - Miroslav Ligas
@MiroslavLigas。我认为他意味着Win 7/8不再使用NTLMv1,因为它被弃用并被认为是开放的漏洞。现在,如果JCIFS仅支持NTLMv1,那么您需要强制使用Win 7/8桌面以允许使用NTLMv1(通过更改Win Registry来完成),以便此类桌面可以与JCIFS一起使用。在大多数公司中,管理员永远不会允许这样的改变。出于所有实际目的,NTLMv1已经死了! - peterh
“JCIFS使用加密技术,包括RC4 128(用于NTLMv2)和AES 256(用于Kerberos)进行身份验证,数字签名和加密。使用加密技术并从美国出口到其他国家的产品应该获得出口分类。”是我在第一页上找到的 jcifs.samba.org ......并且参赛作品是从2009年开始的,所以我打电话给托尼的假设。我从未测试过它... - thecarpy
@thecarpy - JCIFS使用NTLMv2作为CIFS客户端。 JCIFS中的HTTP位从不支持NTLMv2,永远不会支持。 JCIFS中的所有HTTP内容都已弃用,将被删除。 - squarewav


参考: https://jcifs.samba.org/src/docs/faq.html#ntlmv2 

问:jCIFS是否支持NTLMv2?
A: 是。从1.3.0开始,JCIFS完全支持NTLMv2并默认使用它。

注意: 以前包含在JCIFS中的NTLM HTTP SSO过滤器不支持NTLMv2。


0
2018-02-22 19:06