我们尝试在一个HttpClient(一个会话)中向目标服务器发送多个请求。目标服务器将首先使用摘要身份验证(基于MD5-sess)对所有请求进行身份验证。结果表明,只有第一次访问是成功的。以下访问被服务器拒绝,因为服务器将以后的访问视为重放攻击,因为"nc"值始终为"00000001"。
似乎安卓HttpClient将摘要授权标头的格式从"nc"硬编码为"00000001"?
当发送新请求时,客户端有什么方法可以增加这个值?谢谢
公共类HttpService{
private static final HttpService instance = new HttpService();
private HttpService() {
client = getHttpClient();
}
public static HttpService getInstance() {
return instance;
}
private DefaultHttpClient getHttpClient() {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setStaleCheckingEnabled(params, false);
HttpConnectionParams.setConnectionTimeout(params, 15 * 1000);
HttpConnectionParams.setSoTimeout(params, 15 * 1000);
HttpConnectionParams.setSocketBufferSize(params, 8192);
HttpProtocolParams.setUserAgent(params, USER_AGENT);
SchemeRegistry schemeRegistry = new SchemeRegistry();
Scheme httpScheme = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
Scheme httpsScheme = new Scheme("https", SSLCertificateSocketFactory.getHttpSocketFactory(30 * 1000, null), 443);
schemeRegistry.register(httpScheme);
schemeRegistry.register(httpsScheme);
ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);
//create client
DefaultHttpClient httpClient = new DefaultHttpClient(manager, params);
httpClient.getCredentialsProvider().setCredentials(new AuthScope(address, port),
new UsernamePasswordCredentials(username, password));
}
}
Android附带了一个极其过时的(BETA之前的)Apache HttpClient分支。自4.0 ALPHA以来,HttpClient的股票版本已经发生了无数次更改,也在摘要身份验证区域。
你能做的最好的事情是从Apache HttpClient的股票版本复制DigestScheme,并将你的应用程序配置为使用副本而不是默认实现。
https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/DigestScheme.java
为此,您必须向authscheme注册表注册一个自定义DigestSchemeFactory实例。
https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/DigestSchemeFactory.java
看来你是对的。这来自Digest.java
:
//TODO: supply a real nonce-count, currently a server will interprete a repeated request as a replay
private static final String NC = "00000001"; //nonce-count is always 1
你应该在http://b.android.com.你有几个选择:
- 计算摘要并自己创建头,然后在每个请求中设置它。您可以添加一个
HttpRequestInterceptor
使其成为authomatic(不要将凭据设置为凭据提供程序) - AFAIK身份验证方案应该是可插入的,所以要正确地实现摘要身份验证,并配置客户端使用它
- 使用另一个HTTP客户端库
编辑:由于它在库存版本中是固定的,所以还有另一种选择:
另一种选择:
- 使用jarjar更改ApacheHttpClient包名称,将其与应用程序打包,并且根本不使用Android系统