2013-02-27 338 views
2

我试图从网站进行身份验证。我正在使用AsyncHttpClient。下面是我正在尝试的代码。AsyncHttpClient身份验证失败

这里是我的代码,

public class LoginActivity extends Activity { 

    String tag = "LoginActivity"; 
    Button requestBtn; 
    AsyncHttpClient httpClient = new AsyncHttpClient(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_login); 

     requestBtn = (Button) findViewById(R.id.upload_file); 

     PersistentCookieStore myCookieStore = new PersistentCookieStore(this); 
     httpClient.setCookieStore(myCookieStore); 

     httpClient.setBasicAuth(ApplicationConstants.userName, 
       ApplicationConstants.password, new AuthScope(
         "http://*.*.*.*:8080/someUrl", 8080, 
         AuthScope.ANY_REALM)); 




     requestBtn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
     httpClient.get("http://*.*.*.*:8080/someurl",new AsyncHttpResponseHandler() { 

       @Override 
       public void onSuccess(String response) { 
       System.out.println(response); 
       Log.d("Sucessful upload","Onsucess" + response); 
       } 

       @Override 
       public void onFailure(Throwable arg0,String arg1) { 

       Log.d("LoginActivity",arg0.toString()); 
       arg0.printStackTrace(); 
       super.onFailure(arg0, arg1); 
       } 
      }); 
     } 

    } 
    }); 
} 
} 

我得到的,当我在按钮上点击一个例外。它说认证失败 异常Logcat:

02-27 16:02:42.930: D/LoginActivity(8869): org.apache.http.client.HttpResponseException: Unauthorized 
02-27 16:02:42.930: W/System.err(8869): org.apache.http.client.HttpResponseException: Unauthorized 
02-27 16:02:42.930: W/System.err(8869):  at com.loopj.android.http.AsyncHttpResponseHandler.sendResponseMessage(AsyncHttpResponseHandler.java:235) 
02-27 16:02:42.930: W/System.err(8869):  at com.loopj.android.http.AsyncHttpRequest.makeRequest(AsyncHttpRequest.java:79) 
02-27 16:02:42.930: W/System.err(8869):  at com.loopj.android.http.AsyncHttpRequest.makeRequestWithRetries(AsyncHttpRequest.java:95) 
02-27 16:02:42.930: W/System.err(8869):  at com.loopj.android.http.AsyncHttpRequest.run(AsyncHttpRequest.java:57) 
02-27 16:02:42.930: W/System.err(8869):  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442) 
02-27 16:02:42.930: W/System.err(8869):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
02-27 16:02:42.930: W/System.err(8869):  at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
02-27 16:02:42.940: W/System.err(8869):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
02-27 16:02:42.940: W/System.err(8869):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
02-27 16:02:42.940: W/System.err(8869):  at java.lang.Thread.run(Thread.java:856) 

我在做什么错?我使用的URL是正确的。

+0

看起来像用户/密码错误。 – m0skit0 2013-02-27 11:08:52

+0

当我在浏览器上点击相同的凭证时,它可以正常工作 – 2013-02-27 11:10:45

+0

您是否看到'httpClient.get(“http://*.*.*.*:8080someurl”'与'new AuthScope(“http:/ /*.*.*.*:8080/someUrl“'你应该为这样的字符串使用常量 – m0skit0 2013-02-27 11:12:14

回答

5

Basic Authentication with Android

的Android与Apache的HttpClient的4.0 Beta2中,其中有一个缺陷,当它涉及到基本身份验证出货。

当您搜索HttpClient和基本身份验证时,Google肯定会将您发送到HttpClient 3.x的官方文档,它会告诉您如何在preemptive way中执行基本身份验证。这意味着,发送客户的凭据与每个请求,而不是等待401未经授权的响应,然后才发送凭据。这可能是您首先想要的,因为它为您的客户节省了一个请求。

HttpClient client = new HttpClient(); 
client.getParams().setAuthenticationPreemptive(true); 
Credentials defaultcreds = new UsernamePasswordCredentials("username", "password"); 
client.getState().setCredentials(new AuthScope("myhost", 80, AuthScope.ANY_REALM), defaultcreds); 

此示例代码不会用HttpClient版本4进行编译。名为setAuthenticationPreemptive的方法缺失。问题是,如果你忽略这个方法调用,代码仍然有效,但是认证不是抢先的。我们错过了这个小细节,仅在一段时间后才注意到,每个请求之前都有一个未授权的请求/响应周期。这使我们所服务的请求量翻了一番。

现在检查AsyncHttpClient执行:

private final DefaultHttpClient httpClient; 
public void setBasicAuth(String user, String pass, AuthScope scope){ 
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user,pass); 
    this.httpClient.getCredentialsProvider().setCredentials(scope, credentials); 
} 

所以我认为,循环J还可能碰上用做基本身份验证旧的HttpClient 3.x的方式的问题。它确实有用,但它不是抢先的。

一个简单的解决方案将下载loopj的源代码并修改它的源代码并使用修改后的版本。

修改代码将是:的

httpClient.setBasicAuth(ApplicationConstants.userName, 
      ApplicationConstants.password); 

代替

  httpClient.setBasicAuth(ApplicationConstants.userName, 
      ApplicationConstants.password, new AuthScope(
        "http://*.*.*.*:8080/uploadservice", 80, 
        AuthScope.ANY_REALM)); 
+0

非常感谢!!!!做一些工作,然后我会接受你的回答 – 2013-02-27 11:51:52

+0

感谢您的编辑 – StarPinkER 2013-02-27 13:17:59

4

我想你可以通过明确将其处理基本认证头解决此问题。

Context context = this; 
String url = "http://*.*.*.*:8080/someurl"; 

UsernamePasswordCredentials credentials = 
new UsernamePasswordCredentials(ApplicationConstants.userName, 
      ApplicationConstants.password); 

Header header = BasicScheme.authenticate(credentials, "UTF-8", false); 

Header[] headers = {header}; 

RequestParams params = new RequestParams(); 

httpClient.get(context, url, headers, params, new AsyncHttpResponseHandler(){ .. 

如果你想知道服务器响应是什么,也别忘了重写“onComplete”方法。因为在例外情况下,它可能不会通过“onSuccess”和“onFailure”..

+0

没有与我的应用程序的流程,但仍然去吧od建议 – 2013-02-27 13:18:45

+0

这对我有效,谢谢。与上面的解释相反,基本身份验证根本无法使用loopj。 – Alex 2013-07-15 07:37:07

+0

干得好。 :) .. – AAnkit 2013-10-03 16:31:10

11

我想出了另一种解决方案,因为我有代理之间的问题,不喜欢如何授权标题通过使用上述建议的解决方案以及AsyncHttpClient的默认(buggy)setBasicAuth(username, password)实现来构建。

所以我自己添加了头文件,自己做BASE64用户名/密码编码,但是使用从父客户端实现继承的addHeader()方法。

它现在有效。

asyncHttpClient.addHeader(
    "Authorization", 
    "Basic " + Base64.encodeToString(
     (username+":"+password).getBytes(),Base64.NO_WRAP) 
); 

我希望这有助于某人。

+0

甜而短!多年来一直在苦苦挣扎,谢谢你! – Chris 2014-06-04 13:43:48

+0

太棒了!你救了我一周的工作。我完全同意你说setBasicAuth方法是垃圾。 – technik 2017-02-13 21:55:08