russell.ballestrini.net/content/2016-11-21-sharing-a-pyramid-cookie-with-flask-or-tornado.rst
russell@unturf.com 137d65cc65 Consolidate blog tags: 57 → 23 unique tags
- Fix case duplicates (guide→Guide, project→Project, etc.)
- Consolidate single-post tags into broader categories
- Add technology tags (Python, AWS, Salt, Docker, Kubernetes) to 93 posts
- Add lib/tag_stats.py tool for checking tag usage
- Update CLAUDE.md with tag guidelines
2026-01-26 09:09:53 -05:00

168 lines
5.2 KiB
ReStructuredText

Sharing a Pyramid cookie with Flask or Tornado
################################################################
:author: Russell Ballestrini
:slug: sharing-a-pyramid-cookie-with-flask-or-tornado
:date: 2016-11-21 18:35
:tags: Code, Python, Salt
:status: published
Do you have a Pyramid application which authenticates users and uses a signed cookie as a session?
Do you want to build a microservice using another framework and allow it to use the same cookie and session? Me too!
First we will review a bit of Pyramid code which describes the cookie session.
Setup Pyramid Signed Cookie Session
====================================
At the top of your ``__init__.py`` you will have the following import:
.. code-block:: python
# cookie only session, not encrypted but signed to prevent tampering!
from pyramid.session import SignedCookieSessionFactory
In the ``main()`` function of ``__init__.py`` you will create a ``Configurator``:
.. code-block:: python
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application."""
# setup session factory to use unencrypted but signed cookies.
session_factory = SignedCookieSessionFactory(
secret = 'test-secret'
)
# build app config object from ini.
config = Configurator(
settings = settings,
session_factory = session_factory,
)
As you can see for this test example the ``secret`` is hardcoded. A real application would define the secret in the .ini and access it using the ``settings`` object.
Now all new requests will have a ``request.session`` attribute.
You use it like a dictionary, for example:
.. code-block:: python
# set some data into the cookie. for me, this logs the user in.
request.session['authenticated_user_id'] = 8
# get some data from the cookie. for me this gets the user_id or None.
authenticated_user_id = request.session.get('authenticated_user_id', None)
# delete a key / value from cookie. for me this will log out the user.
request.session['authenticated_user_id'] = None
Reference: `SignedCookieSessionFactory <https://docs.pylonsproject.org/projects/pyramid/en/latest/api/session.html#pyramid.session.SignedCookieSessionFactory>`_
Teach Tornado how to read Pyramid cookies
================================================
In this section I'll show you how to access and deserialize the Pyramid cookie from a Tornado application.
To do this, I'm going to extend the Tornado ``Hello, world`` application:
.. code-block:: python
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
This is a simple application which listens to port 8888 and serves the text ``Hello, world`` when ``/`` is requested.
Add the following imports:
.. code-block:: python
# accessing Pyramid cookies.
from webob.cookies import SignedSerializer
from pyramid.session import PickleSerializer
from pyramid.compat import bytes_
For testing purposes, create a global ``serializer`` object:
.. code-block:: python
# https://docs.webob.org/en/stable/api/cookies.html#webob.cookies.SignedSerializer
serializer = SignedSerializer(secret='test-secret', salt='pyramid.session.', serializer=PickleSerializer())
Adjust the ``get`` method in the ``MainHandler`` to look like this:
.. code-block:: python
def get(self):
raw_cookie = self.get_cookie('session', None)
if raw_cookie is not None:
session_data = serializer.loads(bytes_(raw_cookie))
self.write(str(session_data))
self.write(str("<br/>"))
self.write("Hello, world")
The complete program follows:
.. code-block:: python
import tornado.ioloop
import tornado.web
# accessing Pyramid cookies.
from webob.cookies import SignedSerializer
from pyramid.session import PickleSerializer
from pyramid.compat import bytes_
# https://docs.webob.org/en/stable/api/cookies.html#webob.cookies.SignedSerializer
serializer = SignedSerializer(secret='test-secret', salt='pyramid.session.', serializer=PickleSerializer())
class MainHandler(tornado.web.RequestHandler):
def get(self):
raw_cookie = self.get_cookie('session', None)
if raw_cookie is not None:
session_data = serializer.loads(bytes_(raw_cookie))
self.write(str(session_data))
self.write(str("<br/>"))
self.write("Hello, world")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Again, we are hardcoding the same ``secret``. If you set everything up properly, loading ``http://127.0.0.1:8888`` in a web browser should print the cookie session_data in plain-text.
In my testing, I saw my cookie and it looked like this:
.. code-block:: python
(1479520270, 1479516714.062414, {'authenticated_user_id': 5, 'nodes_pending_verify': []})
Hello, world
Thats all for now, let me know what you think in the comments!
.. contents::