其实一般的只要设置一个 BasicScheme 加在 DefaultHttpClient 上面即可进行 BasicAuth 认证, 但是这个简单的方法会出现一些问题, 就是需要进行认证的请求, httpClient都不会在第一次请求服务器的时候携带认证信息, 而是在请求一次被服务器拒绝后再重新发一次请求重新进行认证. 从而导致了重复请求的问题.
通过抓包显示, DefaultHttpClient 里面的是储存了 auth 信息(用户名/密码)的, 但是所有HTTP请求都几乎会做了两遍, 第一次返回 401 unauthorized , 然后 defaultHttpClient 马上进行第二次重复请求, 添加了 auth 信息, 才返回200, 而使用 curl 进行对同样网址进行认证请求时抓包, 结果都是只进行一个请求, 直接返回200, 由此得到了 DefaultHttpClient 在进行 BasicAuth 的这个问题.
唯一的原因只有是 HttpClient 的配置问题, 在查找了大量的关于 org.apache.http.impl.client.DefaultHttpClient 相关资料后才发现正确的配置方法, 可以说是较为复杂的.
先贴代码片段, 注意这里的代码未经过删减, 是我参与的 安能饭否 项目中的实际代码:
/**
* Setup DefaultHttpClient
*
* <p>
* Use ThreadSafeClientConnManager.
* </p>
*
*/
private void prepareHttpClient() {
// Create and initialize HTTP parameters
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 10);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
// Create and initialize scheme registry
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", SSLSocketFactory
.getSocketFactory(), 443));
// Create an HttpClient with the ThreadSafeClientConnManager.
ClientConnectionManager cm = new ThreadSafeClientConnManager(params,
schemeRegistry);
mClient = new DefaultHttpClient(cm, params);
// TODO: need to release this connection in httpRequest()
// cm.releaseConnection(conn, validDuration, timeUnit);
// Setup BasicAuth
BasicScheme basicScheme = new BasicScheme();
mAuthScope = new AuthScope(SERVER_HOST, AuthScope.ANY_PORT);
// mClient.setAuthSchemes(authRegistry);
mClient.setCredentialsProvider(new BasicCredentialsProvider());
// Generate BASIC scheme object and stick it to the local
// execution context
localcontext = new BasicHttpContext();
localcontext.setAttribute("preemptive-auth", basicScheme);
// first request interceptor
mClient.addRequestInterceptor(preemptiveAuth, 0);
}
/**
* HttpRequestInterceptor for DefaultHttpClient
*/
private HttpRequestInterceptor preemptiveAuth = new HttpRequestInterceptor() {
@Override
public void process(final HttpRequest request, final HttpContext context) {
AuthState authState = (AuthState) context
.getAttribute(ClientContext.TARGET_AUTH_STATE);
CredentialsProvider credsProvider = (CredentialsProvider) context
.getAttribute(ClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context
.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
if (authState.getAuthScheme() == null) {
AuthScope authScope = new AuthScope(targetHost.getHostName(),
targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if (creds != null) {
authState.setAuthScheme(new BasicScheme());
authState.setCredentials(creds);
}
}
}
};
/**
* Setup Credentials for HTTP Basic Auth
*
* @param username
* @param password
*/
public void setCredentials(String username, String password) {
mUserId = username;
mPassword = password;
mClient.getCredentialsProvider().setCredentials(mAuthScope,
new UsernamePasswordCredentials(username, password));
isAuthenticationEnabled = true;
}
这里并没有太多可以解释的, 目前看来是进行 BasicAuth 的基本配置, 直接搬去用就可以了. 如果说流量和请求对你的项目来说是一种负担的话.
// first request interceptor
mClient.addRequestInterceptor(preemptiveAuth, 0);
这里会在 httpClient 发出第一次请求前把anth信息强行添加到请求中去, 从而避免了重复请求.
分享到:
相关推荐
DefaultHttpClient绕过安全认证访 DefaultHttpClient 请求绕过 https 实例
NULL 博文链接:https://username2.iteye.com/blog/1664995
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.CoreConnectionPNames; import org.apache....
import com.google.gson.JsonArray; import com.google.gson.JsonObject; import org.apache.... ...import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils;
练习HttpClient的一个Demo
代码如下: public class HttpUtil { public static String ...获取到一个浏览器 HttpClient client = new DefaultHttpClient(); //2.准备请求的地址 try { String arg1 = URLEncoder.encode(name
httpclient过时用的jar包 , 解决项目升级后httpclient过时程序报错
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; 这些...
今天,写了个小代码。...HttpClient httpClient = new DefaultHttpClient(); //创建一个HttpClient HttpGet httpGet = new HttpGet(“http://www.csdn.net/”); //创建一个GET请求 HttpResponse respons
// 发生致命的异常,可能是协议不对或者返回的内容有问题 System.out.println("请检查输入的URL!"); e.printStackTrace(); } catch (IOException e) { // 发生网络异常 System.out.println("发生网络异常!"); ...
httpClient4.5配置SSL绕过https证书,httpClient过时替代方法-附件资源
httpclient的jar包,包含DefaultHttpClient
HttpClient httpClient = new DefaultHttpClient(); //设定目标站点 web的默认端口80可以不写的 当然如果是其它端口就要标明 HttpHost httpHost = new HttpHost("127.0.0.1",80); //设置需要下载的文件 ...
《 httpClient及android 原生接口实现下载并显示图片》博客对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/17609771
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache....
本实例描述了Android平台下使用Apache开源项目的HttpClient访问网络的示例。分别使用HttpClient下的两个子实现类,DefaultHttpClient和AndroidHttpClient分别进行演示。
org.apache.http的相关类,android高版本SDK需要用到,解决'The import org.apache.http.HttpEntity cannot be resolved'>等问题: ...> ★BasicNameValuePair ...> ★DefaultHttpClient cannot be resolved to a type
Android中XML的一些操作 解析类: // 构造方法 public XMLParser() { } /** * 从URL获取XML使HTTP请求 * * @param url ... public String ... DefaultHttpClient httpClient = new DefaultHttpClient()
android HTTPdemo,分别用HttpURLConnection类,和DefaultHttpClient类 实现了 POST、GET方法
new Thread(new Runnable() { public void run() { // TODO Auto-generated method stub try { //设置连接超时 ... DefaultHttpClient httpclient = new DefaultHttpClient( httpParameters);