Development

sfGuardPluginExtraDocumentation/Es

You must first sign up to be able to contribute.

Version 15 (modified by puentesdiaz, 10 years ago)
--

sfGuard plugin - extra documentacion

(esta tratará de ser una ayuda hispana para http://trac.symfony-project.com/wiki/sfGuardPluginExtraDocumentation)

Este wiki brindará información adicional para el uso de sfGuardPlugin en Symfony. Esta dirigido a novatos. Basicamente, amplia el README con información adicional. comentarios y algunas correcciones de la version 1.13 PRE.

Como novato en Symfony y de sfGuardPlugin, busque información en varias partes para entender mas acerca del framework y del este plugin (concretamente , el libro de Symfony y la Guia de Askeet). Este proceso tomo bastante tiempo y fue de gran ayuda. Con este documento trato de ayudar al resto, la info es correcta pero breve, asumo un gran conocimiento general y experiencia.

Introducción a la Autorización, Seguridad y Autenticación

La documentación dice 'The sfGuardPlugin adds authentication and authorization above the standard of Symfony'. Pero que significa todo eso?

Basicamente, autenticación/seguridad es limitar el acceso a (partes de) tu aplicación. Significa que los usuarios tendrán que iniciar una sesión (=autenticacion) para acceder a ciertas areas (=seguridad). Diferentes usuarios pueden tener diferentes 'privilegios' (=autorización). De esta manera aseguras tu aplicación para diferentes tipos de usuarios. También, puedes administrar los privilegios en el back-end (=autorización).

Si lees el capitulo 6 del Libro -'Inside the controller layer', p.100 'Action Security' , te darás una idea del mecanismo de seguridad de Symfony. Aquí un resumen:

El acceso a las 'actions' puede ser restringido en Symfony. La action-access-restriction es seteada en el archivo myProject/apps/myApplication/modules/myModule/config/security.yml (italicas es tu propio proyecto, aplicación y modulo).

Si el usuario pide una action que esta asegurada por security.yml, el usuario tiene:

  1. que ser autenticado (= login)
  2. tener las credenciales correctas (=privilegios adecuados)

Acceder a partes de la aplicación puede ser controlado por las 'Credentials' en security.yml. Para más detalles, mira la página 103 (complex credentials) del Libro de Symfony.

Nota: en esta documentacion nos referimos al usuario como la persona que usa la aplicación desde el frontend. Symfony también tiene el objeto sfUser para el manejo de las sesiones.

La Administración-de-Sesiones es manejada por el objeto sfUser (o $sf_user en los templates). Este es un objeto singleton y puede ser accedido desde cualquier parte de la aplicación. Por ejemplo con $this->getUser()->setAuthenticated(true) seteamos el status a logged-in y puede ser chequeado en tu template con <?php if ($sf_user->isAuthenticated()) ?>.

Puedes agregar más info al objeto sfUser para distinguir entre diferentes tipos de usuarios, agregando 'Credentials' al objeto sfUser:

  1. $this->getUser()->setCredential('member') setea el tipo de usuario a 'member'.

El objeto sfUser es un objeto de sesión. Significa que su información esta disponible a traves de toda la aplicación. Además de Credentials, puedes añadir más información al objeto sfUser que puedas necesitar usando 'Attributes', ej. el ID del usuario:

  1. $this->getUser()->setAttribute('member_id', 123, 'membernamespace') almacena 123 como el member_id, el cual podrá ser usado luego en la aplicación con $this->getUser()->getAttribute('member_id'). El 'namespace' es el nombre para la Colección de Atributos (Espacio de Nombres) y es empleado para facilmente poder eliminar todos los atributos relativos a ese namespace ('membernamespace') (empleando $this->getUser()->getAttributeHolder()->removeNamespace('member')).

Entonces, que pasa cuando un usuario pide una action que esta 'asegurada' a traves del security.yml de un module?

  1. Si el usuario esta autenticado y tiene las correctas credenciales, la action es ejecutada
  2. Si el usuario no esta identificado/autenticado, la accion default login action será lanzada. La default login action esta definida en el 'settings.yml' de tu aplicacion! (myProject/apps/myApp/config/settings.yml). El Libro Symfony menciona al 'security.yml', pero es un error, debería decir 'setting.yml'.
  3. Si el usuario está identificado pero no tiene las credenciales correctas, la default secure action sera lanzada. Tambien esta default secure action esta definida en el 'settings.yml'.

Ambas, la default login y secure action serán re-definidas para usar el sfGuardPlugin. El template para estas actions puede también ser modificado por ti.

Suficiente de las funcionalidades estandar de seguridad de Symfony, volvamos al sfGuardPlugin!

sfGuard plugin

El sfGuard Plugin te brinda el modelo (usuario, grupo y objetos de permisos) y los modulos (backend y frontend) para asegurar tu aplicación en un minuto de configuración.

Instalación

  • Instala el plugin

    symfony plugin-install http://plugins.symfony-project.com/sfGuardPlugin

Este comando instala el plugin dentro de symfony y dentro de tu Proyecto bajo myProject/plugins/sfGuardPlugin. Revisalo, y podrás ver que el plugin tiene sus propios directorios config-, data-, lib-, y un directorio modules para sus cuatro modulos.

sfGuardPlugin añade 4 modulos a tu proyecto en el directorio '/plugins/sfGuardPlugin/modules':

  1. sfGuardAuth - para el frontend-application
  2. sfGuardGroup - para el backend-application
  3. sfGuardPermission - para el backend-application
  4. sfGuardUser - para el backend-application
  • Habilita un o más de estos modulos en tu settings.yml
    • Para tu backend necesitas: sfGuardUser, sfGuardGroup, sfGuardPermission
    • Para tu frontend solo necesitas: sfGuardAuth

Para tu frontend:

    all:
      .settings:
        enabled_modules:      [default, sfGuardAuth]

para tu backend

    all:
      .settings:
        enabled_modules:      [default, sfGuardGroup, sfGuardUser, sfGuardPermission]

Con instalar el Plugin, no significaba que estuvieran activados en Symfony, por lo que necesitabas activarlos (enabled_modules) por aplicación agregando cada uno al 'settings.yml', ej. para frontend o backend (Puedes setear los plugins por aplicacián, y podrás tener diferentes plugins por aplicacion).

  • Limpia el cache

    symfony cc

Cada vez que añadas clases o funciones, tiene que limpiar el cache de symfony.

  • Regenera el modelo

    symfony propel-build-all

Ahora, sfGuardPlugin ha añadido 7 tablas a la Base! Ellas están definidas en '/plugins/sfGuardPlugin/config/schema.xml':

  1. sf_guard_user - La tabla con todos los usuarios, tiene username , password etc.
  2. sf_guard_permission - La tabla con todos los permisos, incluye permissionname y description
  3. sf_guard_user_permission - La tabla que relaciona n:m 'user' y 'permission', es decir un user puede tener multiples permisos y un permiso puede ser compartido con multiples users.
  4. sf_guard_group - La tabla que define groups
  5. sf_guard_user_group - La tabla que lista los users de un group, un user puede ser parte de multiples groups
  6. sf_guard_group_permission - La tabla que relaciona n:m 'group' y 'permission'
  7. sf_guard_remember - almacena la ip-address y remember-key de los users

Comprueba si las tablas son añadidas a su Base, sino, hubo un error.

Luego en la documentación (personaliza el sfAuthUser model) puedes enlazar tu infomación de usuarios a la tabla estandar 'sf_guard_user'.

  • Carga el default fixtures (=database data para ej. testeo) (opcional - crea un superadmin user)

    symfony propel-load-data ''myApplication''

Fixtures son usados para cargar datos en tu Base. Este carga ambos, el actual schema.yml de tu aplicacion, y el schema.yml del plugin dentro de tu Base.(Nota del traductor: Lleve el .yml al /data/fixtures y lo renombre a sfGuardData.yml. Tuve que hacerlo asi. )

  • Opcionalmente habilita el filtro "Remember Me" en filters.yml
        security:
          class: sfGuardBasicSecurityFilter
    

Asegura tu aplicación

Para asegurar una aplicación symfony:

  • Habilita el modulo sfGuardAuth en settings.yml (myProject/apps/myApp/config/settings.yml) del frontend
    all:
      .settings:
        enabled_modules: [..., sfGuardAuth]

Hazlo removiendo el '#' al inicio de la linea de tu 'settings.yml'. Mejor es copiarlo a unas lineas mas abajo sin los '#', esto te dara una vista clara de lo activado (por alguna razón, solo removiendo el '#' no trabajaba).

  • Modifica los modulos login y secure en settings.yml (myProject/apps/myApp/config/settings.yml), y no en 'security.yml' como dice el libro!
  all:
    .actions:
      login_module:           sfGuardAuth
      login_action:           signin

      secure_module:          sfGuardAuth
      secure_action:          secure

Esto cambia el comportamiento por defecto de tu aplicación, cuando el usuario no esta logueado o no tiene las credenciales apropiadas al pedir una página, como se indicó antes en la Introduccion de este wiki.

  • Cambia la clase padre en myUser.class.php de tu aplicación (myProject/apps/myApp/lib/myUser.class.php)
    class myUser extends sfGuardSecurityUser
    {
    }

En Symfony sin el sfGuardPlugin, myUser se basa en sfBasicSecurityUser. Con el anterior cambio, myUser se basa en sfGuardSecurityUser. El sfGuardSecurityUser a su vez se basa en sfBasicSecurityUser, por lo tanto no pierdes ninguna funcionalidad. El sfGuardSecurityUser extiende el sfBasicSecurityUser con métodos tales como signIn y signOut, mira myProject/plugins/sfGuardPlugin/lib/user).

  • Opcionalmente añade estas reglas al routing.yml
    sf_guard_signin:
      url:   /login
      param: { module: sfGuardAuth, action: signin }

    sf_guard_signout:
      url:   /logout
      param: { module: sfGuardAuth, action: signout }

    sf_guard_password:
      url:   /request_password
      param: { module: sfGuardAuth, action: password }

Esto apunta la url .../login a la action 'signin' del modulo 'sfGuardAuth'. Puedes personalizar el parametro url de cada ruta. Esto es opcional porque las anteriores reglas son de routing son automaticamente registradas por el plugin si habilitas el modulo sfGuardAuth. Sin embargo, si lo deseas, puedes deshabilitar las reglas definiendo sfGuardPlugin_routes_register en false en el archivo de configuración app.yml.

N.B.: Si o si debes tener un @homepage (se usa cuando el usuario cierra sesión), por ejemplo:

homepage:
  url:   /
  param: { module: member, action: index }
  • Limpia tu cache

    symfony cc

Cada vez que añadas clases o funciones, tienes que limpiar el cache de symfony.

  • Asegura algunos modulos o toda tu aplicación en security.yml
    default:
      is_secure: on
  • Listo el Pollo :). Ahora, si tratas de acceder a una página segura, serás redireccionado a la página de login. Si has cargado el default fixture, trata de loguearte con admin como username y admin como password.

Añadiendo tu propio user-(profile)-model: Personalizando el modelo de sfAuthUser

El modelo sfAuthUser que viene con el plugin es bastante simple, este tiene:

  • username
  • algorithm
  • salt
  • password
  • created_at
  • last_login
  • is_active
  • is_super_admin

no hay campos/columnas para email o first_name o birthday. Como no quieres cambiar la clase 'sfAuthUser' directamente (porque deseas instalar actualizaciones de este plugin sin tener que agregar tus propios campos una y otra vez), puedes añadir tu propio user-profile en otra clase, la clase user-profile. Por defecto 'sfGuardUser' busca la user-profile-class 'sfGuardUserProfile', que tiene que definir en tu propio 'schema.yml'.

Aqui un ejemplo de una clase sfGuardProfile asociada que puedes añadir al schema.yml de tu proyecto:

    sf_guard_user_profile:
      _attributes: { phpName: sfGuardUserProfile }
      id:
      user_id:     { type: integer, foreignTable: sf_guard_user, foreignReference: id, required: true, onDelete: cascade }
      first_name:  varchar(20)
      last_name:   varchar(20)
      birthday:    date

user_id es la clave foranea a sf_guard_user. Puedes cambiarle el nombre y tambien la user-profile-class asociada en app.yml:

    all:
      sf_guard_plugin:
        profile_class:      sfGuardUserProfile
        profile_field_name: user_id

Ahora puede acceder al perfil via el objeto user:

    $this->getUser()->getGuardUser()->getProfile()->getFirstName()

    // o via proxy method
    $this->getUser()->getProfile()->getFirstName()

El metodo getProfile() obtiene el user-profile-object asociado o crea uno nuevo si este no existe ya.

Cuando elimina un user, tambien se elimina el user-profile asociado.

Administra tus users, permisos y groups en el backend

Para administrar users, permisos y groups, sfGuardPlugin viene con 3 modulos que se integran a tu backend. Estos modulos son auto-generados gracias al symfony admin-generator.

  • Habilita los modulos en settings.yml
    all:
      .settings:
        enabled_modules: [..., sfGuardGroup, sfGuardPermission, sfGuardUser]
  • Accede a los modulos con la ruta tipica:

    http://www.example.com/backend.php/sfGuardUser

Personaliza los templates del modulo sfGuardAuth

Por defecto, el modulo sfGuardAuth viene con 2 muy simples templates:

  • signinSuccess.php
  • secureSuccess.php

Si quieres personalizar uno de estos templates:

  • Crea un modulo sfGuardAuth en tu aplicacion

  • Crea un template con el nombre del template que quieres personalizar en tu directorio templates
  • Symfony ahora renderiza tu template en lugar del por defecto

Personaliza las acciones del modulo sfGuardAuth

Si quieres personalizar o agregar metodos a sfGuardAuth:

  • Crea un modulo sfGuardAuth en tu aplicacion

  • Crea un archivo actions.class.php en el directorio actions que herede de BasesfGuardAuthActions
    <?php

    class sfGuardAuthActions extends BasesfGuardAuthActions
    {
      public function executeNewAction()
      {
        return $this->renderText('This is a new sfGuardAuth action.');
      }
    }

Clase sfGuardSecurityUser

Esta clase hereda de la clase sfBasicSecurityUser desde symfony y es usada por el objeto user object en tu aplicacion (porque tu lo configuraste en el factories.yml anteriormente).

Entonces, para accederlo, puedes usar el clasico $this->getUser() en tus actions o $sf_user en tus templates.

sfGuardSecurityUser añade algunos metodos:

  • signIn() y signOut()
  • getGuardUser() que devuelve el objeto sfGuardUser
  • un grupo de metodos proxy para acceder directamente al objeto sfGuardUser

Por ejemplo, para conseguir el username actual:

    $this->getUser()->getGuardUser()->getUsername()

    // o via proxy method
    $this->getUser()->getUsername()

Super administrator flag

sfGuardPlugin tiene la nocion de super administrator. Un usuario que es super administrator salta todos los chequeos de credenciales.

El super administrator flag no puede ser seteado via web, debes hacerlo directamente en la Base o usar una tarea pake:

    symfony promote-super-admin admin

Validadores

sfGuardPlugin trae un validador que te permitira usarlo en tus modulos: sfGuardUserValidator.

Este validador es usado por el modulo sfGuardAuth para validar un usuario y password y automaticamente loguear al usuario.

Chequear el password con un metodo externo

Si no deseas almacenar la password en la Base porque ya tiene un LDAP server, un .htaccess o si las almacenas en otra tabla, puedes hacer tu propia remota checkPassword (static metodo o funcion) en app.yml:

    all:
      sf_guard_plugin:
        check_password_callable: [MyLDAPClass, checkPassword]

Cuando symfony llame al metodo $this->getUser()->checkPassword(), este llamara a tu metodo o funcion. Tu funcion debe tener 2 parametros, el primero es el username y el segundo es el password. Y debe retornar true o false. Aqui una muestra para tal funcion:

    function checkLDAPPassword($username, $password)
    {
      $user = LDAP::getUser($username);
      if ($user->checkPassword($password))
      {
        return true;
      }
      else
      {
        return false;
      }
    }

Cambiando el algoritmo para almacenar passwords

Por defecto, las passwords son almacenadas como un hash sha1(). Sin embargo, puedes cambiar esto, en app.yml:

    all:
      sf_guard_plugin:
        algorithm_callable: [MyCryptoClass, MyCryptoMethod]

r

    all:
      sf_guard_plugin:
        algorithm_callable: md5

Como el algoritmo se guarda por cada usuario, puedes pensar de otra forma luego y no tendras que regenerar todas las passwords de los usuarios existentes.

Cambiando el nombre o periodo de expiracion de la cookie "Remember Me"

Por defecto, el "Remember Me" crea una cookie llamada sfRemember para 15 dias. Puedes cambiar esto en app.yml:

    all:
      sf_guard_plugin:
         remember_key_expiration_age:  2592000   # 30 dias en segundos
         remember_cookie_name:         myAppRememberMe    # tu nombre para la cookie

Personaliza la redireccion de sfGuardAuth

Si quieres puedes redirigir al usuario a su perfil, luego de loguearse o definir una salida. Puedes cambiar esto, en app.yml:

    all:
      sf_guard_plugin:
        success_signin_url:      @my_route?param=value # el plugin usa la referencia como defecto
        success_signout_url:     module/action         # el plugin usa la referencia como defecto

TODO

  • finish the promote_super_user task
  • finish the getPassword method
  • add support for HTTP Basic authentication

Changelog

1.1.13 PRE

1.1.12

  • fabien: fixed typo in secureSuccess template (closes #2260)
  • fabien: fixed 'secure' action in sfGuardPlugin do not need to be secure (closes #2254)
  • fabien: fixed typo in sfGuardUser::getProfile()
  • fabien: added some check in sfGuardSecurityUser proxy methods

1.1.11

  • fabien: fixed array_merge_recursive causes recursion warnings in sfGuardUser.php (closes #1834)
  • fabien: fixed groups, permissions, and profile saving when sfUser has no primary key (closes #1709)
  • fabien: added connection parameters to all methods that interacts with the database (closes #2237)
  • fabien: changed signout actions, so it doesn't require to be authenticated
  • fabien: added a ->isSuperAdmin() method to the User class
  • fabien: fixed connection should be used when saving model (closes #2152)
  • fabien: fixed typo in modules /sfGuardAuth/config/security.yml (closes #1930)
  • fabien: removed warning about foreign key and profile table
  • davedash: when displaying the signin form, if no referer is set for the user we default to the last page
  • davedash: updated documentation regarding remember me cookie settings (closes #2148)
  • davedash: default algorithm is now sha1 not \asha1\a (closes Ticket #2189)
  • davedash: made the default templates i18n compatible (closes #1662)

1.1.10

  • davedash: reordered the if/elseif structure so no loop starves

1.1.9

  • fabien: fixed a typo in sfGuardUser reloadGroupsAndPermissions() method (closes #1758)
  • fabien: fixed "Remember Me" filter documentation (closes #1705)

1.1.8

  • gordon: add two new config params 'success_signin_url' and 'success_signin_url'
  • gordon: split 'checkPassword()' to 'checkPassword()' and 'checkPasswordByGuard()' so it is callable by your own 'check_password()'
  • gordon: better redirect
  • gordon: 'login_module' and 'login_action' use for 'handleErrorSignin()' and after successe login
  • gordon: Added extra logic to make sure remember me code is only executed if user is not authenticated.
  • fabien: fixed is_super_admin has not default value (closes #1410)
  • fabien: fixed sfGuardPlugin signin.yml validation configuration (closes #1440)
  • fabien: fixed missing unique indexes in sf_guard_group and sf_guard_permission (closes #1454)
  • fabien: fixed sfGuardAuth should clear the credentials (closes #1537)
  • davedash: giving unique indexes unique names so that sfGuardPlugin works with postgres (closes ticket #1720)
  • davedash: fixed the model so getting groupPermissions works (fixes #1729)
  • davedash: the signin class would keep redirecting on itself if the user is logged in

1.1.7

  • fabien: fixed deleting sfGuardUser when no profile is defined (closes #1626)
  • davedash: The setPassword() function of sfGuardSecurityUser() now saves the sfGuardUser object after setting the password