#160 Authlogic
- Download:
- source codeProject Files in Zip (97.4 KB)
- mp4Full Size H.264 Video (22.8 MB)
- m4vSmaller H.264 Video (15.2 MB)
- webmFull Size VP8 Video (42.7 MB)
- ogvFull Size Theora Video (34.4 MB)
Uno de los plugins de Rails más populares es Restful Authentication, que repasamos con detalle en el episodio 67. Restful Authentication es un generador que crea bastante código para gestionar la autenticación en nuestras aplicaciones Rails y funciona muy bien como solución rápida de autenticación pero hoy existen alternativas más flexibles y extensibles.
Una de estas alternativas es Authlogic, que utiliza un enfoque diferente al de Restful Authentication en el sentido de que no genera controladores o vistas sino que sólo trabaja con el código que gestiona la autenticación de los usuarios. Debido a esto lleva un poco más de tiempo hacer que nuestra aplicación funcione con Authlogic porque tendremos que escribir más código, pero ganaremos flexibilidad y control acerca de cómo se presenta la autenticación al usuario.
Cómo añadir Authlogic a una aplicación
Arriba podemos ver una página de la aplicación a la que le vamos a añadir autenticación. En la esquina superior derecha de la página queremos añadir un enlace titulado “Registro” y “Entrar” si el usuario no está logado y “Editar perfil” y “Salir” si lo esta.
Instalación de Authlogic
Podemos instalar Authlogic bien como plugin o como gema; nosotros instalaremos la gema. Para añadirlo a nuestra aplicación sólo tenemos que añadir la siguiente línea al archivo /config/environment.rb
.
config.gem "authlogic"
Después ejecutaremos rake
para asegurarnos de que se ha instalado correctamente la gema.
sudo rake gems:install
Creación del Modelo y del Controlador
Una vez que tenemos Authlogic instalado, lo siguiente que hay que hacer es crear un modelo y un controlador para gestionar a nuestros usuarios. En primer lugar generaremmos nuestro modelo User
.
script/generate model user
En siguiente lugar editaremos el fichero de migración generado para configurar las propiedades de nuestro modelo. Authlogic funciona buscando columnas con un determinado nombre en la base de datos. Nuestro fichero de migracion tendrá el siguiente aspecto:
class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :username t.string :email t.string :crypted_password t.string :password_salt t.string :persistence_token t.timestamps end end def self.down drop_table :users end end
Authlogic reconoce y sabe qué hacer con los campos email
, crypted_password
, password_salt
y persistence_token
. Se puede encontrar más información sobre las columnas especiales de Authlogic en la página de Github de la aplicación de ejemplo de Authlogic
.
Por último, crearemos la tabla en la base de datos con rake
.
rake db:migrate
El modelo User
que acabamos de generar es solamente una clase de modelo estandar. Sólo tenemos que añadir la linea acts_as_authentic
para añadir la funcionalidad de Authlogic.
class User < ActiveRecord::Base acts_as_authentic end
acts_as_authentic
puede recibir un bloque para especificar otras opciones de configuración pero en nuesro caso los valores por defecto son razonables y no lo haremos en esta ocasión.
Antes de continuar crearemos también nuestro controlador de usuarios. Tendremos que tener vistas new
y edit
así que se lo diremos al generador.
script/generate controller users new edit
Tendremos que hacer un pequeño ajuste en el fichero de rutas (/config/routes.rb
) porque vamos a utilizar este controlador como un recurso REST.
Por ahora podremos dejar el controlador tal y como está. Volveremos en breve para rellenar los métodos y vistas que faltan.
Poniendo los enlaces
Ahora que hemos preparado nuestro modelo y controlador pasaremos a crear los enlaces que permiten a los usuarios darse de alta, entrar, salir, o cambiar su perfil. De entrada crearemos el enlace “Registro”, que pondremos en un div en el fichero de layout de nuestra aplicación (/app/views/layouts/application.html.erb
).
<div id="user_nav"> <%= link_to "Registro", new_user_path %> </div>
Como queremos que el enlace aparezca en el lado derecho de la página y además con un tamaño un poco menor, utilizaremos CSS para flotarlo modificando la hoja de estilos
div#user_nav { float: right; font-size: 0.9em; }
Ya tenemos nuestro enlace de registro en todas las páginas de nuestra aplicacion.
El enlace “Registro” lleva a /users/new
, así que nuestra próxima tarea es escribir el código que crea un nuevo usuario. Ya tenemos el controlador y la vista, y el código que nos hace falta es muy sencillo.
def create @user = User.new(params[:user]) if @user.save flash[:notice] = "Te has registrado correctamente." redirect_to root_url else render :action => 'new' end end
Este código de controlador es el estándar en REST. La acción new
crea un objeto de usuario vacío, mientras que la acción create
creará un nuevo usuario a partir de los parámetros enviados y lo guarda en la base de datos si es válido, mostrando otra vez el formulario new
si no lo es.
El formulario de registro se utilizará cuando se registre o edite el perfil de un usuario, por lo que será mejor que lo pongamos en un parcial.
<% title ("Nuevo usuario") %> <%= render @user %>
El código de la vista new.html.erb.
<% form_for @user do |form| %> <%= form.error_messages %> <ol class="formList"> <li> <%= form.label :username, "Nombre de usuario" %> <%= form.text_field :username %> </li> <li> <%= form.label :email, "Email" %> <%= form.text_field :email %> </li> <li> <%= form.label :password, "Clave" %> <%= form.password_field :password %> </li> <li> <%= form.label :password_confirmation, "Confirmación de clave" %> <%= form.password_field :password_confirmation %> </li> <li> <%= form.submit "Enviar" %> </li> </ol> <% end %>
El código _user.html.erb.
Ya podemos pulsar en el enlace “Registro” para ver nuestro formulario de alta. Si intentamos registrarnos sin rellenar ninguno de los campos, veremos que Authlogic proporciona ciertas validaciones automáticas para el modelo User
.
Si rellenamos el formulario correctamente nos redirigirá a la página raiz de nuestro sitio con un mensaje diciendo que nos hemos dado de alta correctamente en la aplicación.
Inicio de sesión
Además del enlace a “Registro” queremos uno de “Entrar” de forma que un usuario registrado pueda iniciar una sesión. Para hacerlo con Authlogic necesitaremos crear otro modelo llamado UserSession que representa la sesión actual del usuario, lo que quiere decir que para iniciar la sesión sólo tenemos que crear un registro UserSession
. Authlogic proporciona un script generador para crear este modelo.
$ script/generate session user_session exists app/models/ create app/models/user_session.rb
Este generador es muy sencillo y tan sólo crea el nuevo modelo UserSession
. Si miramos ese modelo, veremos que es tan sólo una clase vacía que hereda de Authlogic::Session::Base
, pero bastará con eso para gestionar toda la lógica de sesión.
class UserSession < Authlogic::Session::Base end
Dado que el script no crea ningún controlador o vistas aún tenemos que crear el formulario de inicio de sesión. Podemos hacerlo de manera REST creando un controlador UserSessions
y dándole acciones new
, create
y destroy
para crear y destruir sesiones. Sólo tendremos una vista asociada a new
, por lo tanto esa es la única acción que crearemos en el controlador.
script/generate controller UserSessions new
Los tres métodos necesarios en el controlador son, otra vez, los que se verían para cualquier otro controlador. Para new
, tan sólo creamos una nueva instancia de UserSession
.
def new @user_session = UserSession.new end
Para nuestra acción create
crearemos un objeto UserSession
a partir de los parámetros recibidos. Si el usuario es válido el objeto UserSession
tambien lo será y se podrá guardar.
def create @user_session = UserSession.new(params[:user_session]) if @user_session.save flash[:notice] = "Has entrado en la aplicación." redirect_to root_url else render :action => 'new' end end
Por ultimo, en destroy
simplemente tenemos que destruir el objeto UserSession
actual. Obsérvese que no tenemos que encontrar la sesión por id dado que estamos destruyendo la del usuario actual.
def destroy @user_session = UserSession.find @user_session.destroy flash[:notice] = "Successfully logged out." redirect_to root_url end
En la vista new tenemos que definir un formulario para que los usuarios puedan iniciar sesión.
Una vez más, tendremos que modificar nuestro archivo de rutas para que trate el controlador como un recurso y tendremos que añadir un par de rutas con nombre para dar URLs bonitas de registro e inicio de sesión.
map.login 'login', :controller => 'user_sessions', :action => 'new' map.logout 'logout', :controller => 'user_sessions', :action => 'destroy' map.resources :user_sessions
Ya podemos volver al fichero de layout de nuestra aplicación y añadir el enlace de inicio de sesión.
<div id="user_nav"> <%= link_to "Registro", new_user_path %> <%= link_to "Entrar", login_path %> </div>
Ahora ya podemos entrar en la aplicación. Si proporcionamos un nombre de usuario o clave incorrectos el modelo UserSession
se considera no válido y se nos mostrará un mensaje de error.
Si no es así habremos sido redirigidos a la página principal y tendremos una sesión iniciada.
Fin de sesión
No hemos terminado todavía. Después de que hayamos iniciado la sesión aún seguimos viendo los enlaces “Registro” y “Entrar” donde ahora deberíámos ver “Editar perfil” y “Salir”. Para cambiar estos enlaces tendremos que editar otra vez nuestro layout.
No es necesario pasar un identificador de usuario a la acción edit porque siempre vamos a estar editando el usuario actual, así que simplemente basta con pasar :current
. El método current_user que hemos empleado en la sentencia if aún no existe, así que lo vamos a escribir. Querremos que esté disponible en todos los controladores, así que irá en application_controller.rb
.
helper_method :current_user private def current_user_session return @current_user_session if defined?(@current_user_session) @current_user_session = UserSession.find end def current_user @current_user = current_user_session && current_user_session.record end
Hemos añadido dos métodos al controlador de aplicación. El primero, current_user_session
, devuelve la sesión del usuario actual, y el segundo, current_user
, devolverá el modelo User asociado al usuario actual. Haremos que current_user
sea también un método helper de forma que podamos usarlo en nuestras vistas y layout.
Ahora cuando iniciemos la sesión veremos los enlaces correctos.
Tal y como hemos definido a ruta y la acción del controlador, el enlace “Salir” funcionará, pero para editar el perfil tendremos que modificar el controlador UsersController
.
def edit @user = current_user end def update @user = current_user if @user.update_attributes(params[:user]) flash[:notice] = "Perfil actualizado correctamente." redirect_to root_url else render :action => 'edit' end end
Los métodos edit
y update
son un poco diferentes en el sentido de que en lugar de recuperar un modelo por su id
tan sólo obtienen el usuario actual, utilizando el método current_user
que acabamos de escribir en el controlador de aplicación.
Por ultimo, tenemos que poner el formulario del usuario en la vista de la acción edit (/app/views/users/edit.html.erb
).
<% title ("Editar Usuario") %> <%= render @user %>
Ya podemos editar nuestro perfil cuando tenemos sesión iniciada, lo que significa que ya emos implementado toda la funcionalidad que queríamos en nuestro sitio. Los usuarios ya se puedan registrar, iniciar y terminar sesión, así como editar su perfil.
Lecturas Adicionales
La funcionalidad de Authlogic va mucho más allá de lo que hemos visto en este episodio. here’s much more functionality available in Authlogic than we’ve shown in this episode. Para más información, véase la página de Github de Authlogic y la página de su aplicación de ejemplo. También existe la documentación RDoc como referencia.