2010-06-02 29 views
14

Básicamente lo que tengo que hacer es realizar autenticación resumida. Lo primero que intenté fue el ejemplo oficial disponible here. Pero cuando intento ejecutarlo (con algunos pequeños cambios, Post en lugar del método del GET) me siento unApache HttpClient autenticación implícita

org.apache.http.auth.MalformedChallengeException: missing nonce in challange 
at org.apache.http.impl.auth.DigestScheme.processChallenge(DigestScheme.java:132) 

Cuando esto falló Intenté usar:

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

Al principio tengo solo reemplazó los parámetros "DigestScheme" del "reino" y "nonce". Pero resultó que las secuencias de comandos PHP que se ejecutan en el servidor requieren todos los demás parámetros, pero no importa si los especifico o no, DigestScheme no los genera en la Solicitud de AutorPrepertura cuando llamo a su método authenticate(). Y el script PHP devuelve el código de respuesta HTTP 200 con un mensaje que el script PHP requiere los parámetros cnonce, nc y qop.

He estado luchando con esto durante dos días, y sin suerte. Basado en todo, creo que la causa del problema es el script PHP. Me parece que no envía un desafío cuando la aplicación intenta acceder a él sin autorización.

¿Alguna idea a alguien?

Edit: Una cosa más, he intentado conectar con cURL y funciona.

+0

Parece que el servidor está enviando desafíos no estándar. ¿Puedes probarlo en el navegador y obtener un seguimiento del encabezado? –

+0

He hecho una HttpURLConnection al servidor e imprimí los encabezados de respuesta. A continuación se muestra el aspecto de una impugnación: Key = www-authenticate Value = Digest realm = "API REST" qop = "auth" nonce = "4c063992df3dd" opaque = "aba3d4b49c454e1974970e7b5514b001" – anqe1ki11er

Respuesta

3

Logré hacer un inicio de sesión Digest utilizando digestScheme después de verificar el código.

digestAuth.processChallenge(null); 

Obliga a los parámetros de entrada previos a ser interpretados. El parámetro nulo es un encabezado, basado en el encabezado enviado, si hay alguno.

Ahora se usa qop/nc y digestScheme funciona según sea necesario. ejecutarlo en Android

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(); 
} 
+0

¿Cómo puedo determinar el ámbito programáticamente? Este código es para una biblioteca que se ejecutará en muchas computadoras que se conectan a muchos servidores. Entonces no puedo codificarlo. –

-2

Ustedes hacen que sea tan complicado. Si lees la documentación de apache httpclient, sería muy fácil.

protected static void downloadDigest(URL url, FileOutputStream fos) 
    throws IOException { 
    HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getProtocol()); 
    CloseableHttpClient httpClient = HttpClients.createDefault(); 
    HttpClientContext context = HttpClientContext.create(); 

    String credential = url.getUserInfo(); 
    if (credential != null) { 
     String user = credential.split(":")[0]; 
     String password = credential.split(":")[1]; 

     CredentialsProvider credsProvider = new BasicCredentialsProvider(); 
     credsProvider.setCredentials(AuthScope.ANY, 
      new UsernamePasswordCredentials(user, password)); 
     AuthCache authCache = new BasicAuthCache(); 
     DigestScheme digestScheme = new DigestScheme(); 
     authCache.put(targetHost, digestScheme); 

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

    HttpGet httpget = new HttpGet(url.getPath()); 

    CloseableHttpResponse response = httpClient.execute(targetHost, httpget, context); 

    try { 
     ReadableByteChannel rbc = Channels.newChannel(response.getEntity().getContent()); 
     fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 
    } finally { 
     response.close(); 
    } 
} 
1

Este fragmento de código funcionó para mí. Debe proporcionar el dominio que puede obtener mirando el encabezado de respuesta 401 que obtiene del host.

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