【问题标题】:HttpUrlConnection doesn't find the NTLM challenge on AndroidHttpUrlConnection 在 Android 上找不到 NTLM 挑战
【发布时间】:2013-06-18 18:15:23
【问题描述】:

我正在尝试使用 HttpUrlConnection 类将我的 Android 应用程序连接到 IIS 服务器。

我的服务器需要用户进行身份验证,因此它向客户端发送以下质询:

WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM

我的问题是 HttpUrlConnection 似乎没有解析它。所以 getPasswordAuthentication() 永远不会被调用,它会返回一个 IOException “找不到身份验证挑战”。

这是我的代码:

Authenticator.setDefault(new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {                  

            return new PasswordAuthentication("myUsername", "myPassword".toCharArray());
    }               
});

URL url = new URL(myUrl);               
HttpURLConnection conn = (HttpURLConnection) url.openConnection();          

conn.setRequestMethod("GET");
conn.setRequestProperty("Accept-Encoding", "gzip");
conn.setRequestProperty("Accept-Charset", "UTF-8");         
conn.setRequestProperty("Accept", "*/*");
conn.setRequestProperty("Connection", "close");
conn.setDoOutput(true);
conn.setDoInput(true);          

try 
{   
    conn.connect();             
    status_code = conn.getResponseCode();   
}catch (IOException e) {
    ...             
}

我真的开始认为 HttpUrlConnection 不支持 NTLM 挑战。我看到一些似乎可以完成工作的库,但我不想使用外部库。

有人可以确认是否可以让 HttpUrlConnection 在没有外部库的情况下处理 NTLM 挑战?

【问题讨论】:

  • 一个使用 HttpURLConnection 和 jcifs 的example
  • 如果您找到任何解决方案,请分享

标签: android httpurlconnection ntlm android-authenticator


【解决方案1】:

我只能通过设置 AuthScheme 和下面的库使其与 HttpClient 一起工作:http://jcifs.samba.org/src/jcifs-krb5-1.3.17.zip

HttpClient httpclient = new HttpClient(httpParameters, context);
NTCredentials creds = new NTCredentials(“username”, “password”, "", "dir");
httpclient.getCredentialsProvider().setCredentials(
              new AuthScope(context.getString(“whatever is your main URL”), -1), creds);
httpclient.getAuthSchemes().register("ntlm", new NTLMSchemeFactory());

然后你实现 JCIFS 引擎和工厂。你可以在http://hc.apache.org/httpcomponents-client-4.2.x/ntlm.html找到样品

【讨论】:

  • 谢谢!是的,看起来没有办法用当前的 HttpURLConnection 类来做到这一点。问候
  • @NLemay 我有类似的情况,我现在必须重新访问..一旦您成功验证,需要添加什么标头或需要做什么来“保持活动”该连接整个会话?我在这里写了一个详细的问题:stackoverflow.com/questions/18860819/…
  • @whyoz 我刚刚看了你的问题,但我不使用你的图书馆,所以我不知道。但是您是否尝试过 eplozada 的解决方案? HttpClient 是一个广泛使用的库,您将获得更多帮助。但其实我自己并没有试过,我只是决定在Android上不支持NTLM。
  • @NLemay 是的,最终我可以进行身份​​验证并获得 200 状态,但我如何保持它的存在?我可以使用 eplozada 的代码进行身份验证,但这并不能“永久”打开连接。关于这个问题有什么想法吗?
  • 在 android 的 httpsurlconnection 中是否有 NTLM auth 标头的替代方法
【解决方案2】:

我们仍然可以让它与 HttpsURLConnection 一起工作 - 定义一个 Authenticator 并绕过 Certvalidation(信任所有 Certs)

包 com.infosec.utils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLConnect {

        public static void main(String[] args) throws Exception {

            String urlString = System.getProperty("url", "https://yourURLgoesHere:8443/test?");
            CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
            Authenticator.setDefault(new MyAuthenticator("domainname\\yourname", "yourpassword"));


            URL url = new URL(urlString);
            URLConnection urlConnection = url.openConnection();
            HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) urlConnection;
            SSLSocketFactory sslSocketFactory = createTrustAllSslSocketFactory();
            httpsUrlConnection.setSSLSocketFactory(sslSocketFactory);


            try (InputStream inputStream = httpsUrlConnection.getInputStream()) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String line = null;
                while ((line = reader.readLine()) != null) {
              // if you want to print the content
                  System.out.println(line);

                }
            }
        }

      // Trust any Server that provides the SSL certificate by bypassing trust managers 

        private static SSLSocketFactory createTrustAllSslSocketFactory() throws Exception {
            TrustManager[] byPassTrustManagers = new TrustManager[] { new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }

                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                }
            } };
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, byPassTrustManagers, new SecureRandom());
            return sslContext.getSocketFactory();
        }

}

// Authenticator which intercepts and provide required credential

class MyAuthenticator extends Authenticator {
    private String httpUsername;
    private String httpPassword;

    public MyAuthenticator(String httpUsername, String httpPassword) {
        this.httpUsername = httpUsername;
        this.httpPassword = httpPassword;
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        System.out.println("Scheme:" + getRequestingScheme());
        return new PasswordAuthentication(httpUsername, httpPassword.toCharArray());
    }
}

【讨论】:

    【解决方案3】:

    HttpUrlConnection 使用http://jcifs.samba.org/ 与 NTLM 一起工作,该库只需要一些小的调整,例如删除您不需要的 smb java 代码并修复检索 responseCode。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 2015-03-29
      • 1970-01-01
      • 1970-01-01
      • 2022-07-12
      • 1970-01-01
      相关资源
      最近更新 更多