android - 使用 HttpURLConnection 的 NTLM 身份验证

标签 android ntlm

有什么方法可以使用 HttpURLConnection 实现 NTLM 身份验证?目前,我已经使用 DefaultHttpClientJCIFSEngine 实现了身份验证方案。 (我的灵感是:Android: NTLM Authentication, ksoap, and persistent connections)

但是自从删除了 Android 6 Apache HTTP 客户端后,我一直在寻找除了在应用程序 gradle 文件中添加 useLibrary 'org.apache.http.legacy' 之外的解决方案,因为我想改进我的代码使用HttpURLConnection 类。如文档所述,此 API 更高效,因为它通过透明压缩和响应缓存减少了网络使用,并最大限度地降低了功耗。

最佳答案

只有添加库 jcifs,HttpURLConnection 才能与 NTLM 一起使用.

此示例适用于最新的 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 会忽略您在库中定义的 connectTimeoutreadTimeout,这就是为什么当主机没有响应时连接需要很长时间才能断开的原因。使用我在 this SO thread 中描述的代码以避免这个错误。

关于android - 使用 HttpURLConnection 的 NTLM 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32968769/

相关文章:

ubuntu - 无法让 Maven 从代理后面的 HTTPS URL 下载

Android 屏幕尺寸 HDPI、LDPI、MDPI

android - Retrofit2 - 在 GET 请求中发送类型 T 的数组

java - HttpClient 给出与 NTLM 身份验证提供程序的协商错误

c# - 如何使用 HttpWebRequest 使 HTTP 请求通过匿名 NTLM 进行身份验证

ios - AFNetworking NTLM 身份验证?

authentication - 使用 ruby​​ gem、apt-get 等。通过具有 NTLM 身份验证的代理

android - StateListDrawable 在 KeyboardView 的 OnDraw() 方法中不起作用

android - 编译 android 源代码时 linux-x86/bin/acp 的权限被拒绝

android - 更改暴露下拉菜单的背景颜色