I didn't want "msgpad":http://msgpad.com members to have to login every time they started their browser. Ruby On Rails provides session support so that successive requests can be tied to a single user. Unfortunately, the session disappears when the user closes the browser. When the user comes back to your site, RoR creates a new session and the user has to log back in.
If you're reading this then chances are you need to solve this problem. What to do? Well, it's pretty straight forward. The short answer: _Store your own cookie on the clients browser to supplement RoR's _session_id cookie!_ The long answer...
# Understand that a RoR session is a two part tag team.
## The lightweight but dynamic ':_session_id cookie' sits on the clients browser and expires when the user closes the browser.
## The cookies slower, but heavier hitting, super slamming partner called 'the session', sits on the server. It's typically stored as a file in the RAILS_ROOT/tmp/sessions directory.
# Understand that when a user closes their browser, the session becomes void. Don't argue about this, the referee has made his decision. You can get angry and bash RoR around with an aluminium chair if you like... but it won't help, the script was written before you started.
# If a RoR session is an abstraction of requests made by a user while their browser is open. Then we want an abstraction of RoR's sessions. An easy way to accomplish this is to write your own cookie to the browser to supplement RoR's _session_id cookie. This cookie 'tags' the user so we know who he/she is. But unlike RoR's session_id, ensure the cookie expires some time in the future.
# Next, link sessions to the cookie. This is application specific.
# In my case, I wanted to carry over a login session between browser invocations. I also wanted to keep the user logged in 2 days after their last access, but otherwise force the user to log back in. This is a pretty common pattern, so here's my code...
# session[:user] defines a logged in user in this case.
# The idea is that you establish the session[:user] var
# before reaching your controllers.
# If session[:user] still isn't defined by the time your get
# to your controllers you can assume the user isn't logged in.
#
# Make sure you void the cookies on logout!
class ApplicationController < ActionController::Base
before_filter :authenticate_user
def authenticate_user(user=nil)
session[:user] = nil
#forcefully authenticate the session using the passed user.
#used on login and join.
if user
session[:user] = user
#Session isn't verified, but could still be legit via cookies.
#E.g. user might have closed browser window, there by killing the
#session_id cookie. MmMmmm cookie...
elsif cookies[:login] and
user = User.find_by_login(cookies[:login]) and
User.sha1(user.password) == cookies[:password]
session[:user] = user
end
#User's session is authenticated, slide their auth window.
if session[:user]
cookies[:login] = {
:value => session[:user].login,
:expires => 2.days.from_now
}
#We store the password as a hash, rather than the encrypted password.
cookies[:password] = {
:value => User.sha1(session[:user].password),
:expires => 2.days.from_now
}
end
#If we get to here and session[:user] still isn't set, then the
#user isn't authenticated.
end
end