Apache HttpClient摘要式身份验证

Mil*_*lan 14 java android digest-authentication apache-commons-httpclient

基本上我需要做的是执行摘要式身份验证.我尝试的第一件事是这里提供的官方示例.但是当我尝试执行它时(通过一些小的更改,Post而不是Get方法)我得到了一个

org.apache.http.auth.MalformedChallengeException: missing nonce in challange
at org.apache.http.impl.auth.DigestScheme.processChallenge(DigestScheme.java:132)
Run Code Online (Sandbox Code Playgroud)

当这次失败时我尝试使用:

DefaultHttpClient client = new DefaultHttpClient();
client.getCredentialsProvider().setCredentials(new AuthScope(null, -1, null), new UsernamePasswordCredentials("<username>", "<password>"));

HttpPost post = new HttpPost(URI.create("http://<someaddress>"));
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("domain", "<username>"));
post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

DigestScheme digestAuth = new DigestScheme();
digestAuth.overrideParamter("algorithm", "MD5");
digestAuth.overrideParamter("realm", "http://<someaddress>");
digestAuth.overrideParamter("nonce", Long.toString(new Random().nextLong(), 36));
digestAuth.overrideParamter("qop", "auth");
digestAuth.overrideParamter("nc", "0");
digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());

Header auth = digestAuth.authenticate(new
      UsernamePasswordCredentials("<username>", "<password>"), post);
System.out.println(auth.getName());
System.out.println(auth.getValue());
post.setHeader(auth);


HttpResponse ret = client.execute(post);
ByteArrayOutputStream v2 = new ByteArrayOutputStream();
ret.getEntity().writeTo(v2);
System.out.println("----------------------------------------");
System.out.println(v2.toString());
System.out.println("----------------------------------------");
System.out.println(ret.getStatusLine().getReasonPhrase());
System.out.println(ret.getStatusLine().getStatusCode());
Run Code Online (Sandbox Code Playgroud)

起初我只重写了"realm"和"nonce"DigestScheme参数.但事实证明,在服务器上运行的PHP脚本需要所有其他参数,但无论我是否指定它们,当我调用其authenticate()方法时,DigestScheme不会在Authorization RequestPreperty中生成它们.并且PHP脚本返回HTTP响应代码200,其中包含PHP脚本需要cnonce,nc和qop参数的消息.

我已经两天苦苦挣扎,没有运气.根据一切我认为问题的原因是PHP脚本.它看起来当应用程序试图未经授权访问它时它不会发送挑战.

任何人的想法?

编辑:还有一件事,我尝试与cURL连接,它的工作原理.

小智 5

这个代码片段对我有用。您必须提供通过查看从主机获得的 401 响应标头可以获得的领域。

val credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
  new UsernamePasswordCredentials(user, password));
val authCache = new BasicAuthCache();
val digestScheme = new DigestScheme();

digestScheme.overrideParamter("realm", "**Name of the Realm**");
// Nonce value
digestScheme.overrideParamter("nonce", "whatever");

authCache.put(targetHost, digestScheme);

context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);

val httpget = new HttpGet(url);

val response = httpClient.execute(targetHost, httpget, context);
Run Code Online (Sandbox Code Playgroud)


小智 3

digestScheme在验证代码后,我设法使用摘要登录。

digestAuth.processChallenge(null);
Run Code Online (Sandbox Code Playgroud)

强制解释先前的输入参数。null 参数是一个标头,基于发送的标头(如果有)。

现在 qop/nc已使用,digestScheme 按要求工作。在安卓上运行

digestAuth.overrideParamter("algorithm", "MD5");
digestAuth.overrideParamter("realm", serverRealm);
digestAuth.overrideParamter("nonce", Long.toString(new Random().nextLong(), 36));
digestAuth.overrideParamter("qop", "auth");//   not effective 
digestAuth.overrideParamter("nc",""+sequence);//nt effective 
digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
digestAuth.overrideParamter("opaque","ba897c2f0f3de9c6f52d");
String err;
try
{
    digestAuth.processChallenge(null);
    //force  qop in use  chalange  on return header ????!!!!
}
catch (Exception e)
{ 
    err=e.getLocalizedMessage();
}
Run Code Online (Sandbox Code Playgroud)