Tobias K. Tobias K. - 15 days ago 6
Ajax Question

Checking CSRF with multiple gunicorn workers in Pyramid

I'm using Pyramids for my web app, which requires an csrf check for each request. During ajax-calls the csrf-token is set into the header for each request. Everything works fine for 1 thread with 1 worker, but as soon as I enable multiple workers, worker 2 does't know the token from worker 1. How can they share the csrf tokens?

Greetings

production.ini for gunicorn:

[server:main] # GUNICORN
use = egg:gunicorn#main
bind = unix:/tmp/gunicorn.sock
workers = 2
threads = 1
preload = true
reload = true
accesslog = gunicorn_access.log
loglevel = info


In Pyramid I only set:

config.set_default_csrf_options(require_csrf=True)


My HTML-skeletion has:

<input type="hidden" id="hidden_csrf_token" name="csrf_token" value="${request.session.get_csrf_token()}">


And every ajax-request:

var csrf_token = $('#' + hiddenCSRFTokenId).val();
...
headers: {'X-CSRF-Token': csrf_token}


Edit: I'm using the default session factory like

session_factory = session_factory_from_settings(settings)
...
config.set_session_factory(session_factory)


Whereby I wanted to use beaker:

# Beaker cache
beaker.cache.regions = short_term, long_term
beaker.cache.type = memory
beaker.cache.short_term.expire = 3600
beaker.cache.long_term.expire = 86400

# Beaker sessions
beaker.session.type = redis
beaker.session.data_dir = %(here)s/data/sessions/data
beaker.session.lock_dir = %(here)s/data/sessions/lock
beaker.session.autor = true
#beaker.session.type = memory
beaker.session.key = dbas_prototyp
beaker.session.secret = ...
beaker.session.cookie_max_age = 3600
beaker.session.timeout = 3600
beaker.session.cookie_expires = true
beaker.session.url:127.0.0.1:4284


Did I missed something while setting up beaker?

Answer

I think that I've found a first solution that works. I'm using beaker with an simple and external database like:

session.url = postgresql+psycopg2://user:password&@localhost:port/database?client_encoding=utf8

# Beaker cache
beaker.cache.regions = short_term, long_term
beaker.cache.type = ext:database
beaker.cache.short_term.expire = 3600
beaker.cache.long_term.expire = 86400
beaker.cache.extend_existing = True
beaker.cache.table_name = beaker_cache

beaker.session.type = ext:database
beaker.session.key = yyy
beaker.session.secret = xxx
beaker.session.cookie_max_age = 3600
beaker.session.timeout = 3600
beaker.session.cookie_expires = true
beaker.session.table_name = beaker_session

I'll post a solution with redis, after some other issues ware fixed.