= Rack::Session::XFile --- Atomic File-Based Session Management
== Design and implementation
XFile leverages mutex and file locking to guarantee atomic updates to session
data. Exclusive create locks are also used to allocate the resource file when
generating a new session id (SID). This eliminates race conditions and ensures
data consistency for multi-threaded and multi-process applications.
File-based sessions are the fastest and simplest persistent-storage option. To
maximize performance, store session files on an SSD, an in-memory filesystem, or
a disk-based filesystem with performant caching, such as ZFS. Session files are
distributed across 62 directories to minimize access time on some filesystems.
=== Goals
- Simple: We already have a working filesystem; no configuration.
- Reliable: We are using a time-tested filesystem and file lock mechanism.
- Secure: Session data is always stored on the server under our control.
- Performant: Session access is very responsive with memory cache or SSDs.
- Persistent: Sessions persist regardless of application crashes or restarts.
== How session data is stored and referenced
Session data is marshaled and written to the persistent file on the server
associated with the SID. The client cookie (set by the +key+ option) is then
assigned the SID.
== Request filtering
The request filter uses Rack's +skip+ option to completely bypass session
processing for matching requests. When a request matches the filter, a
temporary, in-memory session hash is created instead. The filesystem is never
accessed.
User agents can be filtered by setting the +user_agent_filter+ option with a
regular expression.
This feature was originally implemented to avoid processing sessions for robots.
Many sources state that one-third to two-thirds of all web traffic is from bots.
However, most robots don't store or forward cookies. Consequently, processing
sessions for robots wastes resources and pollutes the session store with
needless "one-time" sessions.
By default, SIDs are validated by the request filtering system to detect SID
tampering, which could lead to directory traversal exploits. Requests with
invalid SIDs are skipped.
== Purging expired session files
The XFile session manager does not concern itself with purging expired sessions.
This task is much better suited for an out-of-band process, such as cron.
For example, run an hourly cron job that executes +find+ and deletes expired
session files. For instance, if the +expire_after+ option is set to 30 days,
then delete session files with last-modification times greater than 30 days.
Additionally, files with modification times past an X amount of time but less
than expiration could be truncated to free up disk space. This effectively
returns an empty session, but will preserve session IDs previously issued to
clients. SID preservation may be critical if these session IDs are referenced by
another backend system or service, such as an analytics system.
=== Example cron job to purge sessions older than 30 days
0 * * * * find /tmp/xfile-sessions -type f -mtime +30 -exec rm -- {} +
=== Example cron job to clear sessions older than 15 days while maintaining SIDs
0 0 * * * find /tmp/xfile-sessions -type f -mtime +15 -exec cp /dev/null {} ;
Caveat: There is potential for a race condition anytime a process modifies
XFile sessions without utilizing file locks. However, in this case with cron,
the potential is very small considering the session files to be deleted haven't
been accessed in a relatively long time and probably won't be any time soon.
== Usage Examples
=== Basic usage with sessions stored under the application directory
require 'rack-session-xfile'
use Rack::Session::XFile,
session_dir: File.join(settings.root, 'tmp/sessions'),
expire_after: 606024*30,
secure: true,
key: 'sid'
By default, sessions are stored in the directory named xfile-sessions under
the operating system's temporary file path.
=== Bypass session processing for robots
require 'rack-session-xfile'
use Rack::Session::XFile,
user_agent_filter: /(bot|crawler|spider)/i
A more extensive filter could include: wget|archive|search|seo|libwww|index.
== Install, test & contribute
-
Install as a system-wide gem.
$ sudo gem install rack-session-xfile
-
Install as a user-local gem.
$ gem install rack-session-xfile --user-install
-
Clone the Mercurial repository.
$ hg clone https://bitbucket.org/pachl/rack-session-xfile
XFile is tested with Christian Neukirchen's awesome test framework,
{Bacon}[https://github.com/chneukirchen/bacon]. First, get bacon. Then crank up
the heat on the entire test suite. Let's get cooking!
$ sudo gem install bacon
$ cd rack-session-xfile
$ bacon -a
If you find or fix a bug, please send reports and patches to pachl@ecentryx.com
or open an issue on the bug tracker.
== Links
Homepage :: https://ecentryx.com/gems/rack-session-xfile
Ruby Gem :: https://rubygems.org/gems/rack-session-xfile
Source Code :: https://bitbucket.org/pachl/rack-session-xfile/src
Bug Tracker :: https://bitbucket.org/pachl/rack-session-xfile/issues
== Compatibility
Rack::Session::XFile was originally developed and tested on
OpenBSD[https://www.openbsd.org] 5.6
using Ruby[https://www.ruby-lang.org] 2.1.2
and Rack[https://github.com/rack/rack] 1.6.0.
Currently, Rack::Session::XFile is compatible with Rack 2.0 and Ruby 2.2+ only.
== History
-
2015-01-29, v0.10.0: First public release
- XFile ran in production for more than a year before public release.
-
2017-06-07, v1.0.0
- Update for compatibility with Rack 2.0 and Ruby 2.2+
(breaks compatibility with Rack 1.x; use XFile 0.10.x)
== License
({ISC License}[https://opensource.org/licenses/ISC])
Copyright (c) 2014-2017, Clint Pachl pachl@ecentryx.com
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.