我试图通过网站进行身份验证。我正在使用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)
我做错了什么?我正在使用的网址是正确的。
答案 0 :(得分:12)
我提出了另一个解决方案,因为我遇到了代理间的问题,这些代理不喜欢使用上面提出的解决方案构建Authorization标头,还有默认(buggy)setBasicAuth(username, password)
实现AsyncHttpClient。
所以我自己添加了标题,自己做了BASE64用户名/密码编码,但使用了从父客户端实现继承的addHeader()
方法。
现在有效。
asyncHttpClient.addHeader(
"Authorization",
"Basic " + Base64.encodeToString(
(username+":"+password).getBytes(),Base64.NO_WRAP)
);
我希望这有助于某人。
答案 1 :(得分:5)
来自Basic Authentication with Android:
Android在Apache的HttpClient 4.0 Beta2中出货,在基本身份验证方面存在缺陷。
当您搜索HttpClient和基本身份验证时,Google肯定会将您发送到HttpClient 3.x的官方文档,该文件向您展示如何在preemptive way中执行基本身份验证。这意味着,在每次请求时发送客户端的凭据,而不是等待401 Unauthorized响应,然后才发送凭据。这可能是你想要的,因为它可以为你的客户节省一个请求。
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的方法。问题是,如果省略此方法调用,代码仍然有效,但身份验证不是抢占式的。我们错过了这个小细节,只是在一段时间后才注意到,每个请求之前都有一个401 未经授权的请求/响应周期。这使我们服务的请求数量增加了一倍。
现在检查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);
}
所以我认为loopj也可能遇到使用旧的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));
答案 2 :(得分:4)
我想你可以通过显式添加处理Basic Auth的标题来解决这个问题。
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”..