2

我试图从网站获得身份验证。我正在使用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)

我做错了什么?我使用的网址是正确的。

4

3 回答 3

12

我想出了另一个解决方案,因为我遇到了中间代理问题,不喜欢使用上述建议的解决方案以及setBasicAuth(username, password)AsyncHttpClient 的默认(错误)实现如何构建授权标头。

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

现在可以了。

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

我希望这对某人有所帮助。

于 2013-12-13T03:50:29.113 回答
5

From Basic Authentication with Android:

Android is shipping with Apache's HttpClient 4.0 Beta2, which has a pitfall, when it comes to Basic Authentication.

When you search for HttpClient and Basic Authentication, Google will most definitely send you to the official documentation of HttpClient 3.x, which shows you, how to do Basic Authentication in a preemptive way. That means, sending the client's credentials with every request, instead of waiting for a 401 Unauthorized response and only then sending the credentials. That's probably what you want to in the first place, because it saves your client a request.

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

This sample code won't compile with HttpClient version 4. The method called setAuthenticationPreemptive is missing. The problem is, if you omit this very method call, the code still works, but the authentication is not preemptive. We missed this little detail and only noticed after a while, that every request was preceded by a 401 Unauthorized request/response cycle. That doubled the amount of requests we served.

Now check the implementation of 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);
}

So I think loopj might also run into the problem of using the old HttpClient 3.x way of doing Basic Authentication. It does work, but it's not preemptive.

A straightforward solution will be download the source code of loopj and modify its source and use the modified version.

Modification in code would be:

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

instead of

            httpClient.setBasicAuth(ApplicationConstants.userName,
            ApplicationConstants.password, new AuthScope(
                    "http://*.*.*.*:8080/uploadservice", 80,
                    AuthScope.ANY_REALM));
于 2013-02-27T11:44:25.577 回答
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”..

于 2013-02-27T12:07:08.450 回答