Вопрос

I'm trying to connect my Android app to an IIS server using the HttpUrlConnection class.

My server needs the user to be authenticate, so it is sending the following challenge to the client :

WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM

My problem is that HttpUrlConnection doesn't seems to parse it. So getPasswordAuthentication() is never call, and it return an IOException "no authentication challenges found".

Here is my code :

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) {
    ...             
}

I'm really starting to think that NTLM challenge is just not supported by HttpUrlConnection. I saw some libraries that seems to do the work, but I would prefer not to use external libraries.

Can somebody confirm if it is possible or not to make HttpUrlConnection handle NTLM challenge without external libs?

Это было полезно?

Решение

I've only been able to make it work with HttpClient by setting the AuthScheme and the library below: 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());

Then you implement the the JCIFS engine and factory. You can find samples in http://hc.apache.org/httpcomponents-client-4.2.x/ntlm.html

Другие советы

We can still make it work with HttpsURLConnection - Define an Authenticator and bypass Certvalidation (Trusting all Certs)

package 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());
    }
}

HttpUrlConnection works with NTLM using http://jcifs.samba.org/ The library just needs some minor adjustments like removing smb java code that you either don't need and fixing retrieving responseCode.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top