2013-02-27 292 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