android android-asynctask digest-authentication

Necesita ayuda para crear la autenticación Digest para Android



android-asynctask digest-authentication (3)

Tengo este código hasta ahora:

private class DownloadWebPageTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... theParams) { String myUrl = theParams[0]; String myEmail = theParams[1]; String myPassword = theParams[2]; HttpPost post = new HttpPost(myUrl); post.addHeader("Authorization","Basic "+ Base64.encodeToString((myEmail+":"+myPassword).getBytes(), 0 )); ResponseHandler<String> responseHandler = new BasicResponseHandler(); String response = null; try { response = client.execute(post, responseHandler); InputStream content = execute.getEntity().getContent(); BufferedReader buffer = new BufferedReader( new InputStreamReader(content)); String s = ""; while ((s = buffer.readLine()) != null) { response += s; } } catch (Exception e) { e.printStackTrace(); } return response; } @Override protected void onPostExecute(String result) { } }

Este código no se compila porque me encuentro con confusión en el punto de:

response = client.execute(post, responseHandler); InputStream content = execute.getEntity().getContent();

Obtuve ese código de retoques con varios ejemplos, y no estoy seguro de qué objeto se supone que es el cliente, y si la primera línea simplemente me dará la respuesta del servidor, o tengo que ir por la ruta de obtener el InputStream y leer el servidor respuesta en?

Por favor, ayúdame a entender cómo hacer esto correctamente.

¡Gracias!


Es posible que desee cambiar a HttpURLConnection . Según este artículo, su API es más simple que la de HttpClient y está mejor soportada en Android. Si elige ir con HttpURLConnection , la autenticación es bastante simple:

Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username", "password".toCharArray()); } });

Después de eso, continúe usando HttpURLConnection como de costumbre. Un simple ejemplo:

final URL url = new URL("http://example.com/"); final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); final InputStream is = conn.getInputStream(); final byte[] buffer = new byte[8196]; int readCount; final StringBuilder builder = new StringBuilder(); while ((readCount = is.read(buffer)) > -1) { builder.append(new String(buffer, 0, readCount)); } final String response = builder.toString();


Logré usar autenticación Digest utilizando OkHttp . En esta muestra de código también uso Dagger y Robospice-retrofit. Lo que hice fue crear un Authenticator OkHttp y asignarlo a mi cliente OkHttp personalizado.

La clase de autenticador implementa un método de autenticación que se invocará cada vez que el servidor encuentre un error 401 y espere la devolución de un encabezado de Autorización (si espera la Autorización Proxy, debe implementar el método authenticateProxy) .

Lo que básicamente hace es envolver llamadas al HttpClient DigestScheme y hacerlo utilizable para OkHttp. Actualmente no aumenta el contador nc. Esto podría causar problemas con su servidor, ya que podría interpretarse como un ataque de reproducción.

public class DigestAuthenticator implements com.squareup.okhttp.Authenticator { @Inject DigestScheme mDigestScheme; @Inject org.apache.http.auth.Credentials mCredentials; @Override public Request authenticate(Proxy proxy, Response response) throws IOException { String authHeader = buildAuthorizationHeader(response); if (authHeader == null) { return null; } return response.request().newBuilder().addHeader("Authorization", authHeader).build(); } @Override public Request authenticateProxy(Proxy proxy, Response response) throws IOException { return null; } private String buildAuthorizationHeader(Response response) throws IOException { processChallenge("WWW-Authenticate", response.header("WWW-Authenticate")); return generateDigestHeader(response); } private void processChallenge(String headerName, String headerValue) { try { mDigestScheme.processChallenge(new BasicHeader(headerName, headerValue)); } catch (MalformedChallengeException e) { Timber.e(e, "Error processing header " + headerName + " for DIGEST authentication."); } } private String generateDigestHeader(Response response) throws IOException { org.apache.http.HttpRequest request = new BasicHttpRequest( response.request().method(), response.request().uri().toString() ); try { return mDigestScheme.authenticate(mCredentials, request).getValue(); } catch (AuthenticationException e) { Timber.e(e, "Error generating DIGEST auth header."); return null; } } }

El autenticador se utilizará en un OkHttpClient creado con un proveedor:

public class CustomClientProvider implements Client.Provider { @Inject DigestAuthenticator mDigestAuthenticator; @Override public Client get() { OkHttpClient client = new OkHttpClient(); client.setAuthenticator(mDigestAuthenticator); return new OkClient(client); } }

Finalmente, el cliente se establece en el servidor RetrofitRobospice en la función createRestAdapterBuilder :

public class ApiRetrofitSpiceService extends RetrofitJackson2SpiceService { @Inject Client.Provider mClientProvider; @Override public void onCreate() { App.get(this).inject(this); super.onCreate(); addRetrofitInterface(NotificationRestInterface.class); } @Override protected String getServerUrl() { return Constants.Url.BASE; } @Override protected RestAdapter.Builder createRestAdapterBuilder() { return super.createRestAdapterBuilder() .setClient(mClientProvider.get()); } }


La versión de HttpClient de Apache incluida con Android se basa en una versión anterior de HttpClient pre-BETA . Hace tiempo que Google recomienda no usarlo y lo elimina en Android 6.0 . El reemplazo HttpURLConnection Google no es compatible con la autenticación HttpURLConnection HTTP , solo básica.

Esto te deja con algunas opciones, que incluyen:

  • HttpURLConnection a HttpURLConnection (como lo recomienda Google) y use una biblioteca, resumen básico , para la autenticación resumida. Ejemplo a continuación.
  • Use la biblioteca OkHttp en lugar de HttpURLConnection o HttpClient . OkHttp no es compatible con el resumen de la caja, pero hay una biblioteca okhttp-digest que implementa un autenticador de resumen. Ejemplo a continuación.
  • Continúe usando el HttpClient (en desuso) agregando explícitamente la biblioteca ''org.apache.http.legacy'' a su compilación, como se menciona en la lista de cambios para Android 6.0 .
  • Hay un proyecto Apache para portar versiones más recientes de HttpClient a Android, pero el proyecto se ha suspendido. Lea más en la página de Apache en HttpClient para Android .
  • Implementa HTTP digerir por ti mismo.

Aquí hay un ejemplo detallado de cómo autenticar una solicitud usando bare-bones-digest y HttpURLConnection (copiado de la página github del proyecto):

// Step 1. Create the connection URL url = new URL("http://httpbin.org/digest-auth/auth/user/passwd"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // Step 2. Make the request and check to see if the response contains // an authorization challenge if (connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { // Step 3. Create a authentication object from the challenge... DigestAuthentication auth = DigestAuthentication.fromResponse(connection); // ...with correct credentials auth.username("user").password("passwd"); // Step 4 (Optional). Check if the challenge was a digest // challenge of a supported type if (!auth.canRespond()) { // No digest challenge or a challenge of an unsupported // type - do something else or fail return; } // Step 5. Create a new connection, identical to the original // one.. connection = (HttpURLConnection) url.openConnection(); // ...and set the Authorization header on the request, with the // challenge response connection.setRequestProperty( DigestChallengeResponse.HTTP_HEADER_AUTHORIZATION, auth.getAuthorizationForRequest("GET", connection.getURL().getPath())); }

Aquí hay un ejemplo usando OkHttp y okhttp-digest (copiado de la página okhttp-digest):

client = new OkHttpClient(); final DigestAuthenticator authenticator = new DigestAuthenticator(new Credentials("username", "pass")); final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>(); client.interceptors().add(new AuthenticationCacheInterceptor(authCache)); client.setAuthenticator(new CachingAuthenticatorDecorator(authenticator, authCache)); Request request = new Request.Builder() .url(url); .get() .build(); Response response = client.newCall(request).execute();