与基本身份验证的HTTPS连接导致未授权

时间:2011-08-18 10:04:59

标签: java android httpclient basecamp

我正试图从我的Android / Java源代码中访问Basecamp API ....

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class BCActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DefaultHttpClient httpClient = new DefaultHttpClient();

        //final String url = "https://encrypted.google.com/webhp?hl=en"; //This url works
        final String url = "https://username:password@projectsource.basecamphq.com/people.xml"; //This don't
        HttpGet http = new HttpGet(url);
        http.addHeader("Accept", "application/xml");
        http.addHeader("Content-Type", "application/xml"); 

        try {

            //  HttpResponse response = httpClient.execute(httpPost);
            HttpResponse response = httpClient.execute(http);

            StatusLine statusLine = response.getStatusLine();
            System.out.println("statusLine : "+ statusLine.toString()); 

            ResponseHandler <String> res = new BasicResponseHandler();  

            String strResponse = httpClient.execute(http, res);
            System.out.println("________**_________________________\n"+strResponse);
            System.out.println("\n________**_________________________\n");

        } catch (Exception e) {
            e.printStackTrace(); 
        }

        WebView myWebView = (WebView) this.findViewById(R.id.webView);
        myWebView.loadUrl(url);//Here it works and displays XML response

    }
}

此网址显示WebView中的回复,但在我尝试通过HttpClient进行访问时显示未经授权的例外,如上所示。

这是通过Android / Java访问 Basecamp API 的正确方法吗? 要么 请给我一个正确的方法。

4 个答案:

答案 0 :(得分:10)

HttpClient 无法从URI中获取登录信用 你必须用指定的方法给它们。

如果你使用 HttpClient 4.x看看这个:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html

但请注意,如果您不想在 HttpClient 上使用新版本(Android使用版本3.x),请看这里:
http://hc.apache.org/httpclient-3.x/authentication.html

这就是理论,现在我们使用它们:
基本上我们使用 HTTP ,但如果您想使用 HTTPS ,则必须将以下作业new HttpHost("www.google.com", 80, "http")编辑为new HttpHost("www.google.com", 443, "https")

此外,您必须编辑主机( www.google.com )以了解您的疑虑 注意:只需要完整的合格域名(FQDN),而不是完整的URI。

HttpClient 3.x:

package com.test;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;

public class Test2aActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        try {
            HttpHost targetHost = new HttpHost("www.google.com", 80, "http");

            DefaultHttpClient httpclient = new DefaultHttpClient();
            try {
                // Store the user login
                httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                        new UsernamePasswordCredentials("user", "password"));

                // Create request
                // You can also use the full URI http://www.google.com/
                HttpGet httpget = new HttpGet("/");
                // Execute request
                HttpResponse response = httpclient.execute(targetHost, httpget);

                HttpEntity entity = response.getEntity();
                System.out.println(EntityUtils.toString(entity));
            } finally {
                httpclient.getConnectionManager().shutdown();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

HttpClient 4.x:

注意:您需要来自Apache的新 HttpClient ,此外您必须重新排列顺序,即jar文件位于Android库之前。

package com.test;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;

public class TestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        try {
            HttpHost targetHost = new HttpHost("www.google.com", 80, "http");

            DefaultHttpClient httpclient = new DefaultHttpClient();
            try {
                // Store the user login
                httpclient.getCredentialsProvider().setCredentials(
                        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                        new UsernamePasswordCredentials("user", "password"));

                // Create AuthCache instance
                AuthCache authCache = new BasicAuthCache();
                // Generate BASIC scheme object and add it to the local
                // auth cache
                BasicScheme basicAuth = new BasicScheme();
                authCache.put(targetHost, basicAuth);

                // Add AuthCache to the execution context
                BasicHttpContext localcontext = new BasicHttpContext();
                localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

                // Create request
                // You can also use the full URI http://www.google.com/
                HttpGet httpget = new HttpGet("/");
                // Execute request
                HttpResponse response = httpclient.execute(targetHost, httpget, localcontext);

                HttpEntity entity = response.getEntity();
                System.out.println(EntityUtils.toString(entity));
            } finally {
                httpclient.getConnectionManager().shutdown();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

答案 1 :(得分:4)

最后我明白了如何粘贴上面回答中显示的代码...

public static void performPost(String getUri, String xml) {

    String serverName = "*******";
    String username = "*******";
    String password = "********";
    String strResponse = null;

    try {
        HttpHost targetHost = new HttpHost(serverName, 443, "https");

        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
            // Store the user login
            httpclient.getCredentialsProvider().setCredentials(
                    new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                    new UsernamePasswordCredentials(username, password));

            // Create AuthCache instance
            AuthCache authCache = new BasicAuthCache();
            // Generate BASIC scheme object and add it to the local
            // auth cache
            BasicScheme basicAuth = new BasicScheme();
            authCache.put(targetHost, basicAuth);

            // Add AuthCache to the execution context
            BasicHttpContext localcontext = new BasicHttpContext();
            localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

            // Create request
            // You can also use the full URI http://www.google.com/
            HttpPost httppost = new HttpPost(getUri);
            StringEntity se = new StringEntity(xml,HTTP.UTF_8);
            se.setContentType("text/xml");
            httppost.setEntity(se); 
            // Execute request
            HttpResponse response = httpclient.execute(targetHost, httppost, localcontext);

            HttpEntity entity = response.getEntity();
            strResponse = EntityUtils.toString(entity);

            StatusLine statusLine = response.getStatusLine();
            Log.i(TAG +": Post","statusLine : "+ statusLine.toString()); 
            Log.i(TAG +": Post","________**_________________________\n"+strResponse);
            Log.i(TAG +": Post","\n________**_________________________\n");

        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

一个非常重要的事情应该如何安排您的图书馆以及您需要哪些图书馆......

enter image description here

Here您可以找到这个库。

在eclipse中添加它们(在Android sdk&lt; 16以下)......

Project properties -> java build path -> Libraries -> Add external JARs

按日食顺序排列......

Project properties -> java build path -> order and export

对于上面的Android sdk&gt; = 16,您必须将这些库放入“libs”文件夹。

答案 2 :(得分:4)

附录中关于CSchulz的精彩和非常有帮助的答案:

在http客户端4.3中:

localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

不再起作用(不推荐使用ClientContext.AUTH_CACHE)

使用:

import org.apache.http.client.protocol.HttpClientContext;

localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);

请参阅http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/protocol/ClientContext.html

http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/protocol/HttpClientContext.html

答案 3 :(得分:1)

如果您想使用其他答案中提到的HttpClient 4.x,您也可以 使用httpclientandroidlib。这是没有apache.commons的转换后的HttpClient库存 并支持Android LogCat。