Hoy en día una tarea bastante común es validar las credenciales de un usuario remotamente. En mi caso necesito que una aplicación ejecutándose en Android se valide en el sistema principal que esta construido con Symfony2 y con FOSUserBundle como proveedor de usuarios.

Ya que FOSUB se encarga de la validación en el sitio web, lo ideal y mas lógico seria que también se encarga de la validación remota, evitando duplicar trabajo y cometer errores. En esencia es el mismo escenario que cuando el usuario quiere iniciar sesión desde un navegador tradicional. Pero con algunas diferencias, así que manos a la obra.

Symfony2

En nuestro proyecto de Symfony tenemos que definir un firewall para hacer accesible la autentificacion via HTTP:

security.yml
1
api:  
  pattern: ^/api/.*  
  stateless: true  
  security: true  
  http_basic:  
    realm: "API"  

access_control:
  - { path: /api/, role: ROLE_USER }

Con estas lineas presentes en el firewall, cada vez que se quiera acceder una ruta del siguiente tipo /api/ se generara una petición para iniciar sesión mediante HTTP.

routing.yml
1
api_login:  
   pattern: /api/login  
   defaults: { _controller: AcmeUserBundle:Security:apiLogin }

En el rounting es necesario indicar el controlador y la acción a realizar.

SecurityController
1
2
3
4
5
6
7
8
9
public function apiLoginAction()  
{

$response = new Response();
$response->setContent('<html><body>OK</body></html>');
$response->setStatusCode(200);
$response->headers->set('Content-Type', 'text/html');

return $response;
}

Y finalmente en el controlador generamos la respuesta, es muy importante indicar el código html de la respuesta para poder saber en Android si el login fue correcto o no.

Android

En Android hay que implementar la siguiente funcion, creando un cliente HTML y dandole una peticion GET para acceder a la URL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public int login(String username, String password) {

HttpClient httpClient = new DefaultHttpClient();

//construir peticion get
HttpGet httpGet = new HttpGet("url");
httpGet.addHeader(BasicScheme.authenticate(
new UsernamePasswordCredentials(username,password), UTF-8", false));

//ejecutar get y recibir respuesta
HttpResponse response = null;
Boolean error = false;
try {
response = httpClient.execute(httpGet);
} catch (ClientProtocolException e) {
error = true;
e.printStackTrace();
} catch (IOException e) {
error = true;
e.printStackTrace();
} finally {
//cerrar conexion http y liberar recursos</span>
httpClient.getConnectionManager().shutdown();
}
return something...
}

Este es el caso mas básico de autentificación, ya que al ser HTTP Basic, el usuario y el password van en texto plano. Pero para la etapa de desarrollo y depuración es bastante útil.