Well perhaps, but only if you're not rebuilding your session when you
change credentials. I'd love to illustrate:
For instance, I wanted a more secure session store for my application.
I didn't like the fact that the default handling used only the
session_id for granting access to session data and I didn't like the
way most "drop-in" authentication systems didn't rebuild the session
during credential changes or access escalations. So I wrote my own.
In my own session handling, I use a mysql back end with a schema just
like the one I showed you earlier in the thread but it also stores the
ip address in a field I call 'host'. I wanted my sessions to use the
remote IP address of the client in addition to the session_id for
controlling access to the session storage. That would help protect my
users from session fixation a little bit, but I also didn't want to
just destroy sessions whose session_id didn't have a matching host
address. Doing that would still leave my my sessions open to denial of
service attacks. For that problem, I had to modify
ActionController::CgiRequest so I can non-destructively rebuild
sessions. I also did not want to endure the overhead of hitting the
database 2 or 3 times extra with each request just to tag each session
with the user_id and host, so I also modified CGI::Session and wrote my
own session store where you can set the host and user_id in the session
object where they will be handled during normal session reads/writes.
To illustrate, here's a piece of my controller:
require 'action_controller_ext' # my changes to ActionController
class ApplicationController < ActionController::Base
before_filter :automatic_login_filter, :touch_session
after_filter :touch_session
protected
def automatic_login_filter
if cookies[:gwb_login_key] =~ /[a-z0-9]{40}/i
key = LoginKey.find_by_key cookies[:gwb_login_key]
if !key.nil? && key.host == request.remote_ip && key.active?
self.app_user = key.user
else
cookies[:gwb_login_key] = nil
end
end
end
def touch_session
# I re-wrote reset_session so that it does not kill the session,
but create a new one
reset_session unless session.host.nil? || session.host ==
request.remote_ip
# These next two lines set attributes in the session store and the
session store
# will update the database normally at the end of the HTTP request.
session.host ||= request.remote_ip
session.user ||= session[:user_id]
end
# rest of the application.rb file omitted
end
I'd post my modifications to CGI::Session and
ActionController::CgiRequest and my session store code, but I'm not
really in a position to do that right this second. My inspiration for
the session store was the mysql_session_store by Stefan Kaes and it
only took me about an hour or so reading the CGI code to figure out how
to modify it to include extra columns.
Also, whenever a user in my application logs in or out, their session
is destroyed and rebuilt--so I never have to worry about a user logging
out and still showing as being "online" when I query the database. I'm
pretty satisfied with it and quite pleased with myself considering I've
only known ruby for about 3 weeks now.
The hardest part was trying to figure out why my controller tests were
failing anytime a session was rebuilt--I had to rewrite bits of the
test session store as a result, but it all works as expected now. I
didn't realize at first that a different session storage apparatus was
used during testing.
Erik