/limited_sessions

Rails 2.3 plugin (see v2.2 tag for Rails 2.1/2.2 version) to enhance Rails' session handling behavior.

Primary LanguageRubyMIT LicenseMIT

LimitedSessions
===============
Copyright 2007-2012 t.e.morgan.
License: MIT

Updates/info: http://iprog.com/projects#limited_sessions
Source: https://github.com/zarqman/limited_sessions
Contact: tm@iprog.com


LimitedSessions provides two distinct features, each in a separate part:
  * Rack-compatible middleware that expires sessions based on inactivity or
    maximum session length. This works with Rails 3 just fine.
  * Rails 3 extension to the ActiveRecord Session Store to auto-cleanup stale
    session records.


Notes on Rails and Rack versions:
  The middleware should be compatible with any framework using a recent
  version of Rack. It was tested with Rack 1.4 and Rails 3.2.
  
  The ActiveRecord Session Store extension requires Rails 3 (and was also
  tested with Rails 3.2).
  
  Versions compatible with Rails 2.3 and Rails 2.2/prior can be found at:
  https://github.com/zarqman/limited_sessions/tree/v2.3 and
  https://github.com/zarqman/limited_sessions/tree/v2.2


Upgrading from previous versions:
  Both initialization and configuration options have changed. See the
  Configuration section below. 
  
  Note that all support for IP address restrictions has been removed. IPv4/IPv6
  dual-stack environments have demonstrated a number of real-world issues, 
  namely user HTTP traffic bouncing between IPv4 and IPv6 resulting in chronic
  session resets. Additionally, homes and offices increasingly have two or more
  ISPs, not to mention mobile devices bouncing between WiFi and 3G/4G networks.
  These scenarios also cause frequent IP address changes.


Features:
  * For all session stores:
    * Configurable session expiry time (eg: 2 hours from last page access)
    * Optional hard maximum limit from beginning of session (eg: 24 hours)
  * When using the ActiveRecord Session Store:
    * DB-based handling of session expiry (activity and hard limits) instead of
      by session paramters
    * Auto-cleaning of expired session records

  
Requirements:
  * Rack and possibly Rails 3
  * Utilizing Rack's (or Rails') sessions support
  * For ActiveRecord session enhancements:
    * Must be using the standard ActiveRecord::SessionStore
      (ActionController::Base.session_store = :active_record_store)
    * Ensure your sessions table has an `updated_at` column
    * If using hard session limits, a `created_at` column is needed too


Installation:
  Add this gem to your Gemfile (Rails) or otherwise make it available to your
  app. Then, configure as required.

  gem 'limited_sessions'


Configuration:
  Rack Middleware with Rails
    1. To either your config/environments/production.rb or your 
       config/application.rb file (depending on if you want this to apply in
       production only or also during development), add the following:

       config.middleware.insert_after ActionDispatch::Flash, LimitedSessions::Expiry, \
         :recent_activity=>2.hours, :max_session=>24.hours

    2. Configuration options.
       The example above shows both configuration options. You may include
       both, one, or none.

       * Session activity timeout *
       Example: :recent_activity => 2.hours
       By default, the session activity timeout is disabled (nil).

       * Maximum session length *
       Example: :max_session => 24.hours
       By default, the maximum session length is disabled (nil).


  Rack Middleware apart from Rails
    1. In your config.ru, add the following *after* the middleware that handles
       your sessions.

       use LimitedSessions::Expiry, :recent_activity=>2.hours, :max_session=>24.hours

    2. See #2 above, under Rack Middleware with Rails, for Configuration options.       


  ActionRecord Session Store
    1. If you don't already have an 'updated_at' column on your sessions table,
       create a migration and add it. If you plan to use the hard session limit
       feature, you'll also need to add 'created_at'.

    2. Tell Rails to use your the new session store. Change 
       config/initializers/session_store.rb to reflect the following:

       <YourApp>::Application.config.session_store :active_record_store
       ActiveRecord::SessionStore.session_class = LimitedSessions::SelfCleaningSession

    3. Configuration options.
       Each of the following options should also be added to your initializer
       file from step 2.


       * Self-cleaning *
       By default, SelfCleaningSession will clean sessions out about every 1000
       page views. Technically, it's a 1 in 1000 chance on each page. For most
       sites this is good. Higher traffic sites may want to increase it to 
       10000 or more. 0 will disable self-cleaning.

       LimitedSessions::SelfCleaningSession.self_clean_sessions = 1000


       * Session activity timeout *
       The default session activity timeout is 2 hours. This uses the 
       'updated_at' column which will be updated on every page load. 

       This can also be disabled by setting to nil. However, the 'updated_at'
       column is still required for self-cleaning and will effectively function
       as if this was set to 1.week. If you really want it longer, set it to
       1.year or something.

       LimitedSessions::SelfCleaningSession.recent_activity = 2.hours


       * Maximum session length *
       By default, the maximum session length handling is disabled. When
       enabled, it uses the 'created_at' column to do its work. 
       
       A value of nil disables this feature and 'created_at' does not need to
       exist in this case.

       LimitedSessions::SelfCleaningSession.max_session = 12.hours


Other questions:
  Do I need both the middleware and the ActiveRecord Session Store?
    No. While it should work, it is not necessary to use both the middleware
    and the ActiveRecord Session Store. If you are storing sessions via AR,
    then use the ActiveRecord Session Store. If you are storing sessions any
    other way, then use the middleware.

  I'm storing sessions in {Memcache, Redis, etc.} and they auto-expire 
  sessions. Do I need this?
    Maybe, maybe not. Normally, that auto-expire period is equivalent to
    LimitedSessions' :recent_activity. If that's all you want, then you don't
    need this. However, if you'd also like to put a maximum cap on session
    length, regardless of activity, then LimitedSessions' :max_session feature
    will still be useful.

  Can I use the middleware with ActiveRecord instead of the ActionRecord
  Session Store enhancement?
    Yes; session expiry (recent activity and max session length) should work
    fine in this circumstance. The only thing you won't get is self-cleaning of
    the AR sessions table.

  How are session expiry times tracked?
    The middleware adds one or two keys to the session data: :last_visit and/or
    :first_visit.
    The AR enhancement uses 'updated_at' and possibly 'created_at'.

  How is this different from using the session cookie's own expires= value?
    The cookie's own value puts the trust in the client to self-expire. If you
    really want to control session lengths, then you need to manage the values
    on the application side. LimitedSessions is fully compatible with the
    cookie's expires= value, however, and the two can be used together.

  What's the difference between :recent_activity and :max_session?
    Recent activity requires regular access on your site. If it's set to 15
    minutes, then a page must be loaded at least once every 15 minutes.
    
    Max session is a cap on the session from the very beginning. If it's set to
    12 hours, then even if a user is accessing the page constantly, and not
    triggering the recent activity timeout, after 12 hours their session would
    be reset anyway.

  Is the AR enhancement compatible with the legacy 'sessid' column?
    No. Please rename that column to 'session_id'.


Other Notes:
  I'm sure there are better ways to do some of what's here, but this seems to
  work. This version has been tested on Rack 1.4, Rails 3.2, PostgreSQL 9.1,
  and Redis 2.2 (via the redis and redis-session-store gems). Other databases
  and session stores should work, but if you find a bug, I'd love to hear about
  it. Likewise, give me a shout if you have a suggestion or just want to tell
  me that it works. Thanks for checking limited_sessions out!
  
      --t (tm@iprog.com; http://iprog.com/)