12

身份验证错误:无法响应任何这些质询:{} Android - 401 Unauthorized

在 Android 上将 HttpPost 与 DefaultHttpClient 一起使用时,我已参考此链接 身份验证错误

我正在开发支持 Drupal 的 android 应用程序。我正在将数据从 android 应用程序发送到 drupal 网站 - JSON 格式的 web 服务。现在我可以从 Drupal webservice 读取 JSON 数据并将其写入我的 android 应用程序。但是在从android上写drupal时遇到问题,它会生成带有状态码的响应

401未经授权

从 android 本机应用程序生成 401 ,而从 phonegap-from android 当我发起 AJAX 请求时,它可以完美运行并在 drupal 网站上写一篇文章或页面。所以这意味着网络服务可以完美地工作&

我的 phonegap android 应用程序完美运行 Android 原生 JAVA 应用程序有问题 我在 Android2.3.4 上运行我的 android 应用程序 -> 三星 Galaxy S Plus - 三星 GT-I9001

这是我的java android代码。

===============================

String url = "XXX";
strResponse1 = makeWebForPostIdea(url,title,body);

public static String makeWebForPostIdea(String url, String title,String body)
    {
        JSONStringer jsonobject = null;
        JSONObject json = null;
        JSONObject jsonnode = null;

        DefaultHttpClient client = new DefaultHttpClient();

Credentials creds = new UsernamePasswordCredentials("username", "password");
        client.getCredentialsProvider().setCredentials(new       AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
 HttpPost post = new HttpPost(url);
System.out.println("value of the post =============> "+post);
 try {
            JSONObject jsonvalue = new JSONObject();
            jsonvalue.put("value", body.toString());

            JSONArray array = new JSONArray();
            array.put(jsonvalue);

            jsonnode = new JSONObject();
            jsonnode.put("und", array);

            System.out.println("@@@@@@2    jsonnode=======>"+jsonnode.toString());


        } catch (JSONException e3) {
            // TODO Auto-generated catch block
            e3.printStackTrace();
        }
 try {
 jsonobject = new JSONStringer().array().object().key("und").object().key("0").object().key("value").value(body).endObject().endObject().endObject().endArray();
    System.out.println("=============>"+jsonobject);

        } catch (JSONException e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }

         List<NameValuePair> params = new ArrayList<NameValuePair>();

                 params.add(new BasicNameValuePair("type","page"));

            params.add(new BasicNameValuePair("title",title));
            params.add(new BasicNameValuePair("language","und"));
            params.add(new BasicNameValuePair("body",jsonobject.toString()));

            System.out.println("value of the params =============> "+params);

        UrlEncodedFormEntity formEntity = null;
        try {
                formEntity = new UrlEncodedFormEntity(params);
        } catch (UnsupportedEncodingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        post.setEntity(formEntity);

        try {

            HttpResponse response = client.execute(post);

            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("=========> statusCode post idea=====> "+statusCode);    
            if (statusCode == HttpStatus.SC_OK)
            {
                HttpEntity entity = response.getEntity();
                InputStream is = entity.getContent();
                return iStream_to_String(is);
            }
            else
            {
                return "Hello This is status ==> :"+String.valueOf(statusCode);
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return null;
    }

     public static String iStream_to_String(InputStream is1) {
            BufferedReader rd = new BufferedReader(new InputStreamReader(is1), 4096);
            String line;
            StringBuilder sb = new StringBuilder();
            try {
                while ((line = rd.readLine()) != null) {
                    sb.append(line);
                }
                rd.close();

            } catch (IOException e) {
                // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String contentOfMyInputStream = sb.toString();
        return contentOfMyInputStream;
            }

    }

   }

这是我得到的logcat。

 08-09 12:41:29.063: I/System.out(336): value of the post =============>      org.apache.http.client.methods.HttpPost@4053c3c8
 08-09 12:41:29.093: I/System.out(336): @@@@@@2    jsonnode=======>{"und":  [{"value":"ddddddd"}]}
 08-09 12:41:29.093: I/System.out(336): =============>[{"und":{"0":{"value":"ddddddd"}}}]
 08-09 12:41:29.103: I/System.out(336): value of the params =============> [type=page, title=hhhh, language=und, body=[{"und":{"0":{"value":"ddddddd"}}}]]
 08-09 12:41:30.913: W/DefaultRequestDirector(336): Authentication error: Unable to respond to any of these challenges: {}
 08-09 12:41:30.913: I/System.out(336): =========> statusCode post idea=====> 401
 08-09 12:41:30.924: I/System.out(336): =========> Response from post  idea => Hello This is status ==> :401

这是我的 PhoneGap Ajax 请求,它运行良好。

$('#page_node_create_submit').live('click',function(){

  var title = $('#page_node_title').val();
  //if (!title) { alert('Please enter a title.'); return false; }

  var body = $('#page_node_body').val();
  //if (!body) { alert('Please enter a body.'); return false; }

  // BEGIN: drupal services node create login (warning: don't use https if you don't     have ssl setup)
  $.ajax({
      url: "XXX",
      type: 'post',
      data: 'node[type]=page&node[title]=' + encodeURIComponent(title) +  '&node[language]=und&node[body][und][0][value]=' + encodeURIComponent(body),
      dataType: 'json',
      error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert('page_node_create_submit - failed to login');
        console.log(JSON.stringify(XMLHttpRequest));
        console.log(JSON.stringify(textStatus));
        console.log(JSON.stringify(errorThrown));
      },
      success: function (data) {
      $.mobile.changePage("index.html", "slideup");
     }
  });
  // END: drupal services node create

  return false;

});

==================================================== ================================

编辑 :

我为我的错误尝试了 Apache httpclient 的各种方法。这段时间我做了一些研究并在谷歌上搜索并发现了一些有趣的东西。

我发现 Android-Google 官方不推荐我在代码中使用的 Apache HttpClient 的第一件事。检查此链接。在来自 Dalvik 团队的 Jesse Wilson 的链接消息中。他们建议使用 HttpURLConnection 而不是 DefaultHttpClient 并且还写道 Android 团队将不再开发 Apache httpclient 。所以它是我正在使用的旧版本。

http://android-developers.blogspot.in/2011/09/androids-http-clients.html

我从这个链接中找到的第二件事。这表明 Android 附带了 Apache 的 HttpClient 4.0 Beta2,它在基本身份验证方面存在缺陷。 我使用的身份验证方法是 HttpClient 3.x ,我从这个链接中找到了。检查链接。 http://hc.apache.org/httpclient-3.x/authentication.html#Preemptive_Authentication

所以版本问题。

http://dlinsin.blogspot.in/2009/08/http-basic-authentication-with-android.html

我还发现了一些可能解决此问题的链接。

http://ogrelab.ikratko.com/using-newer-version-of-httpclient-like-4-1-x/

Android 上的 Apache HttpClient 4.1

Android 1.6 中捆绑了哪个版本的 Apache HTTP 客户端?

从这些链接中,我得出一个结论,如果我们将 Apache HttpClient 升级到最新的稳定版本,那么这个问题就可以解决。

但这直接是不可能的,因为Android Team已经正式停止了对Apache httpclient的支持。

有了这个链接就可以解决了。我还没有尝试过,但我正在努力。

它是可以帮助升级 Android 中的 httpclient 版本的库。

http://code.google.com/p/httpclientandroidlib/

另一个解决方案可能是使用HttpURLConnection。我也在研究它。

但是,stackoverflow 和 Internet 上的大多数人似乎都将DefaultHttpCLient与 Android 一起使用。当然,它也在我的整个应用程序中与我一起工作,包括登录、注册、从服务器和会话读取以及其他功能。只是它不能直接将一些文章发布到我的服务器-Drupal 网站。在服务器上注册用户期间,它与 POST 请求完美配合。

所以朋友们,对此有什么建议吗?为什么它不适用于发布文章?

4

4 回答 4

2

它是如何从 PhoneGap 而不是 Java 的。PhoneGap 在 Web 容器中运行应用程序,因此已经过身份验证 - 您拥有所有正确的 cookie。AJAX 将共享相同的会话,并且一切都“正常工作”。

然而 HTTPClient 是完全不同的——您正在启动一个全新的 HTTP 会话,并且一切都必须正确。

关于 HTTP Auth 工作原理的一些评论:

有几种 HTTP 身份验证方法 - 选择哪种方法是 Web 服务器。在继续之前,请检查您的 Drupal 配置以确定它是否是:

(另请注意,Web 容器具有“智能”功能,能够根据服务器的请求尝试不同的身份验证方法,所有这些都在幕后进行)

还要检查 Drupal 网络日志。几点建议:

  • 你有没有看到 HTTPClient连接并且 URL 是否指向正确的资源。从服务器的角度来看总是值得检查...
  • 它去了正确的服务器吗?可能出错的一个示例:您是否在 URL 中针对多宿主 Web 服务器使用 IP 地址,因此请求转到了错误的服务器?
  • 检查客户端预先发送的身份验证是否是正确的类型(基本、摘要、NTLM)

让我知道这是否有帮助。如果没有,您可以根据这篇文章提供更多详细信息,我可以跟进更多建议。

于 2012-08-15T06:03:21.447 回答
1

您可以尝试检查:How to do http post using apache httpclient with web authentication?

HttpInterceptor在需要时使用 a 注入身份验证数据

于 2012-08-09T10:25:50.817 回答
1

我在使用loopj android-async-http 库(强烈推荐)的 Drupal 服务中遇到了相同的“DefaultRequestDirector:身份验证错误:无法响应任何这些挑战:{}”问题。

对我来说,解决方案的关键在于 Jose L Ugia 在其中一个关于特别注意 Drupal 的 JSON 输出的答案中的评论。我试图捕获一个 JSONObject,但真正的消息是数组格式“[”错误的用户名或密码。“]”。切换到 JSONArray 正确地捕获了错误并允许我处理它。在您的情况下,我相信这是因为您没有像 drupal 服务所期望的那样发布登录凭据。

您应该记住,使用 Drupal 服务您应该执行系统/连接并获取会话,然后是用户/登录(以及作为参数传入的用户/密码)并获取会话,然后您的所有后续请求都应该工作。这就是我喜欢使用 loopj 库的原因,因为它使所有这些请求更易于管理。这是一个使用 loopj 连接到 drupal 的非常基本的示例。所有后续帖子都可以使用参数轻松完成。

public class Loopj {
  private static final String TAG = "loopj";

  private static AsyncHttpClient client = new AsyncHttpClient();
  private final PersistentCookieStore myCookieStore;


  public Loopj(Context context) {
    myCookieStore = new PersistentCookieStore(context);
    client.setCookieStore(myCookieStore);
    client.addHeader("Content-type", "application/json");
  }


  public void systemConnect(String uri) throws JSONException {
    client.post(uri + "/endpoint/system/connect", new JsonHttpResponseHandler() {
      @Override
      public void onSuccess(JSONObject json) {
        Log.i("TAG", "Connect success =" + json.toString());
      }

      @Override
      public void onFailure(Throwable e, String response) {
        Log.e("TAG", "Connect failure");
      }
    });
  }

  public void userLogin(String uri) throws JSONException {
    RequestParams params = new RequestParams();
    params.put("username", username);
    params.put("password", password);
    client.post(uri + "/endpoint/user/login", params, new JsonHttpResponseHandler() {
      @Override
      public void onSuccess(JSONArray response) {
        Log.i("TAG", "Login success =" + response.toString());
      }

      @Override
      public void onFailure(Throwable e, JSONArray json) {
        Log.e("TAG", "Login failure");
      }
    });
  }
于 2012-08-23T17:12:15.480 回答
1

我建议先测试应用程序的 PHP 端。有几种方法可以进行自己的调用,包括标头和身份验证。从 curl 到 GraphicalHttpClient(http://itunes.apple.com/us/app/graphicalhttpclient/id433095876?mt=12,我个人使用它,它工作得很好)。还有一些其他选项,例如 REST 客户端调试器(https://addons.mozilla.org/en-US/firefox/addon/restclient/)

通过这种方式,您将能够以多种方式测试您的调用,这在客户端中直接进行是很痛苦的(有时它只是从 http 更改为 https 或在 Authorization 标头中添加您的令牌类型,这更容易制作n 飞)。

一旦一切按预期工作,在您的客户端中重现相同的调用、标头和正文,您就可以开始了。

于 2012-08-18T08:47:13.777 回答