Simple Login with Facebook, con symfony 1.4 y doctrine

2 votes, 5.00 avg. rating (100% score)

Ahora vamos a ver algo que esta muy de moda, casi todas las pagina como slideshare, scribd ya casi no usan sus propios formularios de registro y de login, todo esto lo han reemplezado por un simple boton

previamente tienen que estar registrados al facebook y tener una aplicación facebook developer, y tener la “App ID/API Key” y el “Código secreto de la aplicación”, fundamental conseguir esto antes de continuar.

ahora vamos a implementar esta funcionalidad con symfony, vamos a empezar de 0

php symfony generate:project connect
php symfony generate:app frontend
php symfony generate:module frontend Home

ahora vamos modificar el archivo config/doctrine/schema.yml y agregar esta definición de la tabla usuario

User:
  tableName:                 t_user
  actAs:
    Sluggable:               { fields: [ username ] }
    Timestampable:
  columns:
    id:                      { type: integer  , length: 20 , primary: true    , autoincrement: true        }
    fullname:                { type: string   , length: 200                   , notnull: true              } 
    username:                { type: string   , length: 50                    , notnull: true              }
    password:                { type: string   , length: 255                   , notnull: true              }
    email:                   { type: string   , length: 100                   , notnull: true              }
    url:                     { type: string   , length: 255                                                }
    phone:                   { type: string   , length: 100                                                }
    active:                  { type: string   , length: 1  , fixed: true      , notnull: true , default: 0 }
    facebook_id:             { type: string, length: 20                                                    }
  indexes:
    i_username:              { fields: [ username ]                                                        }
    u_email:                 { fields: [ email ]                              , type: unique               }
    u_facebook_id:           { fields: [ facebook_id]                         , type: unique               }    
    i_url:                   { fields: [ url ]                                                             }
    i_active:                { fields: [ active ]                                                          }
  options:
    symfony:                 { filter: false, form: true }

corremos el comando de para generar todo

php symfony doctrine:build --all --and-load

para este ejercicio vamos a crear dentro del modulo Home de la aplicacion frontend 2 acciones index y panel
dentro de la carpeta apps/frontend/modules/Home, vamos a crear la carpeta config y dentro un archivo security.yml
que va a contener lo siguiente:

panel:
  is_secure: on

ahora vamos a modificar el archivo apps/frontend/template/layout.php

debería quedar así

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <?php include_http_metas() ?>
    <?php include_metas() ?>
    <?php include_title() ?>
    <link rel="shortcut icon" href="/favicon.ico" />
    <?php include_stylesheets() ?>
    <?php include_javascripts() ?>
  </head>
  <body>
    <?php echo $sf_content ?>
 
    <div id="fb-root"></div>
    <script>
      window.fbAsyncInit = function() {
        FB.init({appId: 'App ID/API Key', status: true, cookie: true, xfbml: true});
    };
    (function() {
        var e = document.createElement('script');
        e.async = true;
        e.src = document.location.protocol +
                '//connect.facebook.net/en_US/all.js';
        document.getElementById('fb-root').appendChild(e);
    }());
    </script>
  </body>
</html>

luego modificamos el archivo apps/frontend/modules/Home/templates/indexSuccess.php agregamos el botón que nos va a loguear a facebook

<div id="social-register" class="registration_panel">
<a id="facebook-login" class="fb_button fb_button_medium" href="/Home/login">
<span class="fb_button_text">Login with Facebook</span>
</a>
</div>

ahora en el archivo apps/frontend/modules/Home/actions/action.class.php agregamos executeLogin, para que el enlace anterior pueda inciar sesión en los servidores de facebook, aquí tienes que poder tus datos de seguridad generados por facebook, IMPORTANTE: el capo $my_url tiene que estar en un hosting publico para que facebook pueda redireccionarse a tu sitio con el código y el estado.
la primera parte es cuando no estamos logeados a facebook, entonces te redirecciona a la pagina de inicio de sesión de facebook, y le mandamos nuestra url con un token para evitar ataques de tipo CSRF, luego se valida que los códigos sean iguales y que corresponda a la misma sesión, y con ese código recién podemos utilizar la api de facebook, para traernos la información del usuario, te lo devuelve en json, pero fácilmente podemos convertirlo a un objeto de tipo php, y lo que sigue es comprobar si ya se había conectado con facebook a nuestra pagina, sino comprobamos si ya se había registrado por nuestro sistema con su email, y por ultimo es un usuario nuevo y de plano usamos su irformacion para registrarlo, al final activamos la sesión y guardamos el id del usuario para utilizarlo posteriormente y se va a redirigir al panel. al final si no coinciden los estados lo redirigimos al error404, para evitarnos problemas

<?php
 class HomeActions extends sfActions
{
  public function executeLogin(sfWebRequest $request)
  {
   $app_id     = "xxxxxxx";
   $app_secret = "xxxxxxxxxxxxxxxxxxxxxx";
   $my_url     = "http://mysite.com/Home/login";
   $code       = $request->getParameter("code");
   $state      = $request->getParameter("state");   
 
   if(empty($code)) 
   {
     $this->getUser()->setAttribute('state' ,md5(uniqid(rand(),TRUE)));
     $dialog_url = sprintf("https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s&state=%s", $app_id, urlencode($my_url) ,$this->getUser()->getAttribute('state'));
     return $this->redirect($dialog_url); 
   }      
   if($state == $this->getUser()->getAttribute('state') )
   {
 
     $token_url = sprintf("https://graph.facebook.com/oauth/access_token?client_id=%s&redirect_uri=%s&client_secret=%s&code=%s", $app_id, urlencode($my_url), $app_secret, $code);
 
     $response = @file_get_contents($token_url);
     $params   = null;
     parse_str($response, $params);
 
     $graph_url = sprintf("https://graph.facebook.com/me?access_token=%s", $params['access_token'] );
     $user      = json_decode(file_get_contents($graph_url));
 
     $myUser    = Doctrine::getTable('User')->findOneByFacebookId($user->id);
     if(!$myUser)
     {
       $myUser = Doctrine::getTable('User')->findOneByEmail($user->email);
       $myUser->setFacebookId($user->id);
       $myUser->save();
     }
 
     if(!$myUser)
     {
       $myUser = new User();     
       $myUser->setFullname($user->name);
       $myUser->setUsername($user->username);
       $myUser->setEmail($user->email);
       $myUser->setUrl($user->link);           
       $myUser->setFacebookId($user->id);
       $myUser->save();
     }
 
     $this->getUser()->setAuthenticated(true);
	 $this->getUser()->setAttribute('user_id' ,$myUser->getId());
     return $this->redirect('Home/panel');        
   }
   else {
	 $this->forward404();
   }
  }
 
  public function executeIndex(sfWebRequest $request)
  {
  }
 
  public function executePanel(sfWebRequest $request)
  {
    $this->user = Doctrine::getTable('User')->findOneById($this->getUser()->getAttribute('user_id'));
  } 
}
?>

ahora en el archivo panelSuccess.php

le ponemos el mensaje de bienvenida

Welcome <?php $user->getFullname(); ?>, to mySite

y deberia verse asi

Recomiendoel uso de este codigo cuando tienes una aplicacion symfony con un modulo de seguridad propio y no tienes el sfDoctrineGuardPlugin instalado, por que casi la mayoria de los plugin de facebook como sfFacebookConnect, sfMelodyPlugin, etc estan integrados con sfDoctrineGuard.

les dejo el codigo fuente :)

2 votes, 5.00 avg. rating (100% score)

Deje un comentario


*