Cookies and sessions in Rails 2.0

By Myles Eftos

As we know, HTTP – the protocol that the web is built on is stateless – meaning that every transaction with the server doesn’t know anything about the previous transactions. To get around this, we use cookies to track session and emulate statefulness. Basically a cookie is stored on the users computer, which provides a key that the server can use to retrieve any session information.

In previous versions of Rails, we had a number of choices for our session stores – PStore, ActiveRecordStore, DRbStore and MemoryStore. PStore was always the default, which stored session data in a temporary file. This scheme did have a number of limitations such as race conditions in certain situations (That is, if two instances tried to write to the same session at the same time, your data could be come clobbered – storing a large information from an number of AJAX calls is one cause) as well as scaling issues – running multiple servers is pretty well impossible using PStore.

As a result most production systems would use one of the other stores, notably ActiveRecordStore which stores all of the session data in the system database.

To get around these limitations in PStore, Rails 2.0 will be introducing a new default store: CookieStore which stores all session information in one or more cookies on the clients computer. For anyone giving this a cursory glance, this may seem like a security risk, and it could be – however there are a few things you can do as a developer to make the process much more secure.

First of all, let me point out that the the store isn’t stored in plain text – there is a new forgery key in the environment.rb file, which you should set to a long, random string. The session information is hashed against this key, so the server can check for forgery attempts. So the first step is to ensure that this key is suitably long and suitably random.

Secondly, don’t store sensitive information in the session hash. Most application can get away with only storing a user id. This is a best practice thing – and isn’t just Rails-centric.

Thirdly, if you are especially paranoid, look at one of the other session store options. CookieStore really is the lowest-common denominator option, and one of the other store types would probably be more suitable for production systems anyway. You can see descriptions of the other store types on Scott Barron’s blog. He also benchmarks the different types of stores (Note though that as the article is quite old now, the new Cookie Store isn’t included in the benchmarks).

  • wwb_99

    Outside of the security issue, I can see another huge one–all your session variables got alot more expensive. A big part of the reason that people moved to sessions and away from cookies was that all that data was not pushed down to the client and back but rather remained on the server. So, depending on what you are keeping in the session, it could easily clobber your site.

  • Philippe Rathe

    Well as of today (december 5 2007), edge Rails generates a 127 bytes secret for the session.That’s long. One week ago, edge rails was generating a 32 bytes secret.

    My question is : Should we rely on the Rails generator for production if we choose CookieStore? Even if the generator seems good, it’s still public.

  • madpilot

    wwb_99: Yes, this is a good point, although some may argue that if you are keeping that much data in the session, perhaps you should reconsider your flow. Having said that, if you do need to store a large amount of data in a session PStore probably isn’t a good bet either, so you would be using one of the other solutions anyway.

    Philippe: There has been a push on the core-dev list for a generator rake task – if that makes it through, there is no real reason to USE the default value. I’m of the opinion that you should generate your own key for each application.

  • Don Park

    “First of all, let me point out that the the store isn’t stored in plain text – there is a new forgery key in the environment.rb file”

    a SHA is a one-way hash. the session is stored in the cookie in plain text along with the hash. any tampered-with session data is rejected, but the data itself is in plain view. (note i havent used cookie session store myself, this info comes from my reading on the topic)

  • madpilot

    Hi Don,

    I stand corrected on that comment – I just went through the source code, and you you are right – it is just a base64 encoded version of a Marshalled object with a hashed digest that you can compare against.

    As I said before – if you have any info in there that you didn’t want sniffed, use one of the other stores.

  • m1ke

    Is there a way of having rails NOT storing 127 chars for a session ID? Sure, security is one thing, but let’s assume that guessing 127 chars is pretty difficult for most rails apps out there.

  • Eric Larson

    I am wondering how turn this off as well, as programmable clients or curl don’t easily work with the cookie bits. I’m writing a service that won’t be used by a browser and won’t use any cookies.

  • madpilot

    Hi Eric,

    I’ve never had any problems with curl and sessions (cookie-based ones or otherwise), how ever, if you wanted to turn them off completely create a file called no_store.rb in the lib/ directory and drop this code in there:

    require 'cgi'
    require 'cgi/session'

    class CGI::Session::NoStore
    def initialize(session, options = {}); end

    def restore

    def update; end
    def close; end
    def delete; end

    then add this to you environment.rb file (Near commented out line about active_record_store):

    require 'no_store'
    config.action_controller.session_store = :no_store

    This is effectively a session store that does nothing, so technically cookies are still turned on, but they are disabled.

    Hope that helps.

  • madpilot

    Sorry about the formatting there, Looks like you can’t use pre tags or br tags in comments…



Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.