【问题标题】:HTTPS connection with basic auth result into Unauthorized带有基本身份验证的 HTTPS 连接导致未经授权
【发布时间】:2011-08-18 10:04:58
【问题描述】:

我正在尝试按照以下方式从我的 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

    }
}

此 URL 显示 WebView 中的响应,但当我尝试通过 HttpClient 访问时显示未经授权的异常,如上所示。

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

【问题讨论】:

    标签: java android httpclient basecamp


    【解决方案1】:

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

    【讨论】:

    • 你读过我的cmets吗?您正在尝试使用 HttpClient 版本 4.x 并需要库并更改库的顺序
    • HttpClient 库必须在 android 库之前。不知道你用的是哪个IDE。在 Eclipse 中,您可以在 project properties -> java build path -> order and export 中进行设置
    • 你把HttpHost改成443https了吗?
    • 总是查看类的java doc,有很多可用的信息并使用搜索引擎查找应用程序的特殊情况。 https 使用 443 端口,http 使用 80 端口是基本的网络知识。
    • 如果不在现有的 Android 上添加额外的库,这是否可以工作?我得到了一个找不到 org.apache.http.auth.Credentials 的类。
    【解决方案2】:

    我终于明白了如何粘贴上面答案中显示的代码...

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

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

    Here 你会找到这个库。

    在eclipse中添加它们(低于Android sdk

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

    在eclipse中按顺序排列它们...

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

    对于以上 Android sdk >= 16,您必须将这些库放入“libs”文件夹中。

    【讨论】:

    • 我收到此错误:AUTH_CACHE 无法解析或不是字段
    • @EliMiller 按照答案中的说明重新排序您的库。将参考库放在 android jar 上方。
    【解决方案3】:

    附录关于 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

    【讨论】:

      【解决方案4】:

      如果您喜欢使用其他答案中提到的 HttpClient 4.x,您也可以 使用httpclientandroidlib。这是一个没有 apache.commons 的转换股票 HttpClient 并支持 Android LogCat。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-24
        • 1970-01-01
        • 1970-01-01
        • 2021-07-17
        • 2018-06-13
        • 2021-02-16
        相关资源
        最近更新 更多