score.session¶
A small module for handling sessions. Originally written for web usage, but can be used outside of web environments without any constraints.
Quickstart¶
For a quick integration of this module, just add it and score.kvcache
to
your modules list. It also makes sense to disable the https-only flag during
development:
[score.init]
modules =
score.ctx
score.session
score.kvcache
[session]
# cookies are allowed on non-HTTPS sites during development:
cookie.secure = False
[kvcache]
# default backend, we're configuring a sqlite file in
# the same folder as this config file:
backend.default = score.kvcache.backend.FileCache
backend.default.path = ${here}/_cache.sqlite3
# session cache:
container.score.session.backend = default
You should now have a new context member called session, which
behaves just like a regular dict. It will start out without an id, but will
gain a uuid4
string once it contains something:
>>> ctx.session.id
>>> ctx.session['parrot'] = 'dead'
>>> ctx.session.id
b9a1aa34-e44a-4370-9d06-1431ab692b94
If you want to access a specific session, you have to set ctx.session_id before accessing the session:
>>> ctx.session_id = 'b9a1aa34-e44a-4370-9d06-1431ab692b94'
>>> ctx.session['parrot']
'dead'
If you’re using the score.http
module, there is nothing more to do: The
module will automatically set appropriate session cookies and load the sessions
if it receives them back.
Configuration¶
-
score.session.
init
(confdict, db=None, kvcache=None, ctx=None)[source]¶ Initializes this module acoording to our module initialization guidelines with the following configuration keys:
- db.class [default=None]
- The
path
to the database class, that should be used as backend. - kvcache.container [default=score.session]
- The name of the cache container to use for storing session
data when using
score.kvcache
as backend. - kvcache.livedata [default=false]
- This value defines whether sessions must always pull the newest session data for every operation. This has the advantage that all session data will be immediately up-to-date across all processes using the same session, but also the disadvantage that it will make using the session a lot slower.
- ctx.member [default=session]
- This is the name of the context member, that should be
registered with the configured
score.ctx
module (if there is one). - cookie [default=session]
- Name of the cookie to set when used in combination with the
score.http
module. It is recommended to provide a non-default, obscure value here. Setting this value to the string None will disable setting cookies. - cookie.max_age [default=None]
- The max-age parameter of the cookie. The default value of None means that the cookie will be valid until the browser is closed.
- cookie.path [default=/]
- The path parameter of the cookie.
- cookie.domain [default=None]
- The domain parameter of the cookie.
- cookie.secure [default=True]
- The secure parameter of the cookie. Please be aware that you are exposing your user sessions to man-in-the-middle attacks (like wireless sniffers), if you set this value to False in production.
- cookie.httponly [default=True]
- The httponly parameter of the cookie. Please be aware that setting this value to False in production can lead to session hijacking, if an attacker manages to sneak in malicious javascript code into your application (using XSS, for example).
Details¶
Loading Sessions¶
Sessions can be accessed through the methods create
and load
on the configured module. If you
are using score.ctx
, though, you can set the context’s session id on the
context:
>>> ctx.session_id = 'b9a1aa34-e44a-4370-9d06-1431ab692b94'
>>> ctx.session['username']
'sirlancelot'
Note
The name of the id-member is constructed using the configured context
member. If you have configured your score.session to register its context
member as storage
, the id-member will be storage_id
:
>>> ctx.storage_id = 'b9a1aa34-e44a-4370-9d06-1431ab692b94'
>>> ctx.storage['username']
'sirlancelot'
You must take special care when using this approch, since the id-member will only be read once: whenever you access the ctx.session for the first time. The following corde leads to undefined behaviour:
# WARNING! Broken code! Always set ctx.session_id *before*
# accessing ctx.session for the first time!
ctx.session['parrot'] = 'passed on'
ctx.session_id = 515
Backends¶
The module is capable of storing session data in either of two backends: a
score.kvcache
container, or a score.db
table.
Using score.kvcache
is much easier, but does not allow you to access all
sessions of a single user efficiently, for example. It merely stores a mapping
of session ids to session data. This should really not come as a big surprise
when using the key-value-cache as backend.
The alternative backend is score.db
. Its usage requires a bit more
configuration. Not only in your configuration file …
[session]
db.class = path.to.Session
… but also in your application: you will need a database class with an additional mixin from this package:
from .storable import Storable
from score.db import IdType
from score.session.db import DbSessionMixin
from sqlalchemy import Column, ForeignKey
from sqlalchemy.orm import relationship
class Session(Storable, DbSessionMixin):
user_id = Column(IdType, ForeignKey('_user.id'))
user = relationship('User', backref='sessions')
This approach has the advantage that you can operate on sessions just like any other database entity. There is also a small drawback, however: You can no longer delete the user_id on your sessions:
>>> ctx.session['user_id'] is None
True
>>> del(ctx.session['user_id'])
>>> ctx.session['user_id'] is None
True
>>> del(ctx.session['I-dont-exist'])
KeyError: 'I-dont-exist'
The mixin will allow you to write arbitrary values, just like before:
>>> ctx.session['actor_id'] = 14
>>> ctx.session['parrot'] = 'ceased to be'
These additional values will be stored as JSON value in the column _data
:
sqlite> .schema _session
CREATE TABLE _session (
_uuid VARCHAR(36) NOT NULL,
_data VARCHAR NOT NULL,
actor_id INTEGER,
_type VARCHAR(100) NOT NULL,
id INTEGER NOT NULL,
PRIMARY KEY (id),
UNIQUE (_uuid),
FOREIGN KEY(actor_id) REFERENCES _actor (id)
);
sqlite> select * from _session;
a9fd7ad0-1ed0-45ab-bf5f-bb2b00741ded|{"parrot": "ceased to be"}|14|session|1
API¶
-
class
score.session.
ConfiguredSessionModule
(ctx, ctx_member, cookie_kwargs)[source]¶ This module’s
configuration class
.-
ctx_member
¶ Name of the registered context member, or None if no context member was registered.
-