仅针对LG G3 6.0执行Apache HTTP客户端Android异常

时间:2016-02-29 20:25:12

标签: android apache-commons-httpclient

我已经接管了一个Android应用程序,该应用程序拍摄照片并将它们附加到公司所在基地的大型软件系统的工作中 - 直到最近它才能正常工作。

似乎只有已经升级到Android 6.0的LG G3手机才会出现例外情况:

public static String frapiGetRequest(String transaction, ArrayList<Content> parameters) {
    StringBuilder builder = new StringBuilder();
    DefaultHttpClient client = new DefaultHttpClient();
    HttpHost targetHost = new HttpHost(HOST,PORT,SCHEME);
    String url = SCHEME + "://" + HOST + "/" + transaction;
    if (parameters != null && parameters.size() > 0) {
        url += "?" + buildParameterString(parameters);
    }

    Utilities.bLog(TAG, "Making FrapiRequest -- " + url);

    try {
        HttpGet getRequest = new HttpGet(url);
        client.getCredentialsProvider().setCredentials(
                new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                new UsernamePasswordCredentials(USERNAME, PASSWORD));

        /**Exception Occurs Here**/
        HttpResponse response = client.execute(getRequest);


        StatusLine statusLine = response.getStatusLine();
        int statusCode = -1;

        statusCode = statusLine.getStatusCode();
        if (statusCode == 200) {
            HttpEntity entity = response.getEntity();
            InputStream content = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(content));
            String line;
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
            Utilities.bLog(TAG,"Frapi Request Succeeded");
        } 
        else {
            Utilities.bLog(TAG, "Frapi Request Failed: " + url);
        }

    } catch (ClientProtocolException e) {
        e.printStackTrace();
        Utilities.eLog(e);
    } catch (IOException e) {
        e.printStackTrace();
        Utilities.eLog(e);
    } catch (Exception e) {
        e.printStackTrace();
        Utilities.eLog(e);
    }
    return builder.toString();
}

堆栈跟踪

java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
at org.apache.http.impl.auth.DigestScheme.isGbaScheme(DigestScheme.java:210)
at org.apache.http.impl.auth.DigestScheme.processChallenge(DigestScheme.java:176)
at org.apache.http.impl.client.DefaultRequestDirector.processChallenges(DefaultRequestDirector.java:1097)
at org.apache.http.impl.client.DefaultRequestDirector.handleResponse(DefaultRequestDirector.java:980)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:490)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
at com.rossware.sd_quickpics.Utilities.frapiGetRequest(Utilities.java:111)
at com.rossware.sd_quickpics.Business.authenticate(Business.java:83)
at com.rossware.sd_quickpics.MainActivity$AuthenticateAsyncTask.doInBackground(MainActivity.java:320)
at com.rossware.sd_quickpics.MainActivity$AuthenticateAsyncTask.doInBackground(MainActivity.java:307)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)

这还没有在任何其他手机上报告..我会使用HttpURLConnection但它不支持摘要式身份验证(目前我们的frapi服务器正在使用)

我不确定是否有任何方法可以继续使用我们拥有的身份验证机制,或者我是否必须在frapi中实现不同的协议(希望不会破坏我们现有的所有应用程序..)或者如果有其他方法可以为这些手机的人们绕过这个问题?这个问题非常有限(一个客户拥有大约10部电话,而不是世界末日,但绝对是他们的主要问题)

我可以用android来解决受影响用户的这类问题吗?看起来代码是不正确的吗?

2 个答案:

答案 0 :(得分:0)

可以将DigestAuth与HttpUrlConnection一起使用:

private InputStream connect(String urlStr, String username, String password) throws Exception {

    URL url = new URL(urlStr);
    HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection();
    connection.setDoInput(true);
    connection.setRequestMethod("GET");

    try {

        return connection.getInputStream();

    } catch(Exception e) {

        if (connection.getResponseCode() == 401) {

            String header = connection.getHeaderField("WWW-Authenticate");

            String uri = new URL(urlStr).getFile();

            String nonce = Tools.match(header, "nonce=\"([A-F0-9]+)\"");
            String realm = match(header, "realm=\"(.*?)\"");
            String qop = match(header, "qop=\"(.*?)\"");
            String algorithm = match(header, "algorithm=(.*?),");
            String cnonce = generateCNonce();
            String ha1 = username + ":" + realm + ":" + password;
            String ha1String = md5digestHex(ha1);
            String ha2 = "GET" + ":" + uri;
            String ha2String = md5digestHex(ha2);
            int nc = 1;
            String response = ha1String + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2String;
            String responseString = md5digestHex(response);


            String authorization =
                "Digest username=\"" + username + "\"" + 
                ", realm=\"" + realm + "\"" +
                ", nonce=\"" + nonce + "\"" +
                ", uri=\"" + uri + "\"" +
                ", qop=\"" + qop + "\"" +
                ", nc=\"" + nc + "\"" +
                ", cnonce=\"" + cnonce + "\"" +
                ", response=\"" + responseString + "\"" +
                ", algorithm=\"" + algorithm + "\"";


            HttpURLConnection digestAuthConnection = prepareConnection(urlStr);
            digestAuthConnection.setRequestMethod("GET");
            digestAuthConnection.setRequestProperty("Authorization", authorization);

            return processResponse(digestAuthConnection);

        } else throw e;
    }
}

public static String match(String s, String patternString, boolean strict) {

    if (!isEmpty(s) && !isEmpty(patternString)) {
        Pattern pattern = Pattern.compile(patternString);
        if (pattern != null) {
            Matcher matcher = pattern.matcher(s);
            if (matcher != null && matcher.find() && (matcher.groupCount() == 1 || !strict)) {
                return matcher.group(1);
            }
        }
    }
    return null;
}

public static String match(String s, String patternString) {
    return match(s, patternString, true);
}

public static byte[] md5Digist(String s) {
    try {
        MessageDigest md5 = MessageDigest.getInstance("md5");
        md5.update(s.getBytes());
        return md5.digest();
    } catch (NoSuchAlgorithmException e) {
        return null;
    }
}

public static String digest2HexString(byte[] digest) {

   String digestString="";
   int low, hi;

   for (int i = 0; i < digest.length; i++) {
      low = (digest[i] & 0x0f ) ;
      hi  = ((digest[i] & 0xf0) >> 4);
      digestString += Integer.toHexString(hi);
      digestString += Integer.toHexString(low);
   }
   return digestString;
}

public static String md5digestHex(String s) {
    return digest2HexString(md5Digist(s));
}

public static String generateCNonce() {
    String s = "";
    for (int i = 0; i < 8; i++) {
        s += Integer.toHexString(new Random().nextInt(16));
    }

    return s;

}

答案 1 :(得分:0)

我今天遇到了类似的问题,刚开始使用HttpClient for Android

  1. 向build.gradle添加了依赖项{{1}。
  2. compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'替换为new DefaultHttpClient()
  3. 在代码的其他部分可能还需要制作一些其他的小型重构,但这应该非常简单。