Sessiones y galletitas en rails
Si alguna vez te ha tocado hacer alguna aplicación web ligéramente seria te habrás peleado, seguramente, con el manejo de sesiones y las cookies.
Como seguramente sepais HTTP es un protocolo sin estado y de tipo pregunta-respuesta. Con esto quiero decir que, al menos en principio, ninguna petición HTTP tiene constancia de la anterior. Yo sencillamente mando mis consultas HTTP como por ejemplo “dame la página a.html” y el servidor, en principio siempre procesará la petición de la misma manera. ¿Como resolvemos este entuerto? Uno de los métodos es utilizar cookies. Una cookie almacena el estado de una aplicación web en el lado del cliente y así se puede mantener una información de estado de la aplicación. Hay más factores que juegan en todo esto pero para hacernos una idea básica a grandes rasgos con esta explicación nos sirve. Hay otros métodos como añadir a la URL de la aplicación un identificador de sesión pero no los trataremos hoy.
El manejo de sesiones en Rails se hace a través de una estructura que utilizaremos como si fuese un mapa (aunque en realidad no lo sea). Podemos meter en la sesión de la aplicación prácticamente cualquier cosa gracias a la serialización así que si es necesario no teneis porque cortaros.
Si alguno ha trabajado con PHP el almacenamiento por defecto de las sesiones en Rails es muy similar. En el directorio temporal del servidor (/tmp normalmente) se creará los archivitos necesarios para almacenar sesiones. El problema es que Rails es bastante más extensivo creando archivos que PHP así que rápidamente nos puede inundar el directorio temporal de miriadas de ficheros. Eso, evidentemente afectará sobremanera al rendimiento de nuestra aplicación. Así que tampoco trataremos el almacenamiento por defecto de las sesiones sino que almacenaremos las sesiones en base de datos. Es una alternativa bastante elegante y normalmente el rendimiento es razonablemente bueno. Así pues: ¡manos a la obra!
Como ya hemos dicho crearemos la migración para que nos cree la tabla de la BD para almacenar la info de sessión
Samarkand:MiApp rafael$ rake db:sessions:create (in /Users/rafael/workspace/MiApp/MiApp) exists db/migrate create db/migrate/20090510105331_create_sessions.rb Samarkand:MiApp rafael$ rake db:migrate (in /Users/rafael/workspace/MiApp/MiApp) == CreateSessions: migrating ================================================= -- create_table(:sessions) -> 0.0041s -- add_index(:sessions, :session_id) -> 0.0040s -- add_index(:sessions, :updated_at) -> 0.0048s == CreateSessions: migrated (0.0142s) ========================================
Si revisamos la migraciones para ver como es esta tabla veremos que es bastante sencilla. Tan solo tiene el session id los datos y los timestamps.
Ahora nos tocará editar el enviroment.rb y cambiar el modo en el que se almacenan por defecto los datos de sesión a el modo de base de datos. Buscamos las líneas
# Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information # (create the session table with "rake db:sessions:create") # config.action_controller.session_store = :active_record_store
y descomentamos la última línea para cambiar al active record store. Como ya hemos comentado vamos a utilizar el método de las cookies para almacenar el identificador de la sesión en el cliente. El cliente para identificar la cookie necesita darle un nombre. Por defecto utiliza el nombre del servidor así que si tienes más de una aplicación en el mismo servidor es recomendable cambiarle el nombre. Si os soy sincero es recomendable cambiarle el nombre siempre porque nunca se sabe cuantas aplicaciones tendremos en un mismo sitio en el futuro. Para cambiar el nombre de la cookie nos vamos al application.rb y añadimos la siguiente línea.:
session :session_key => '_miapp_session_id'
Con esto tendremos que la cookie de nuestra aplicación se llame ‘_miapp_session_id’.
También tendremos que descomentar el secret de la linea
protect_from_forgery # :secret => 'un numero largo y complicado'
dejándola así
protect_from_forgery :secret => 'un numero largo y complicado'
ya que no utilizamos el almacenamiento de cookies por defecto.
Así, a partir de ahora en cualquiera de nuestros controladores podemos añadir objetos a nuestra sesión sesión utilizando:
session[:unaclave] = unobjeto
o recuperarlos
@mivariable = session[:unaclave]
Sencillo y eficaz. Eso si, tened en cuenta que esto solo funcionará en navegadores que tengan las cookies activadas. ¿A que ahora comprandeis porque tantos sitios las piden?
Más información:






Buffff, a mi lo de las cookies nunca me ha gustado mucho, además si la web es dinámica atacando constantemente a una BD para mostrar contenidos una query más o menos para las sesiones tampoco se nota mucho en rendimiento.
es cierto lo comentado pero para estas cuestiones hay que acostumbrarse a trabajar seriamente y acoger cada aplicación con la profesionalidad requerida; y para mi en lo particular creo que por cuestiones de seguridad es mejor de esta implementación. Muchas gracias por el aporte de rafadc