So, if you check your Django database for sessions, you’ll see that session_data is stored as a signed text.
For database-backed setup, this should not be necessary at all since this signed token is never exposed to users, unlike in django.contrib.sessions.backends.signed_cookies. Additionally this behavior comes with some drawbacks:
- There is a (small) performance overhead due to signing/unsigning during each request
- SECRET_KEY rotation affects sessions, which is unnecessary
- You cannot query sessions using session data
- Resulting database queries to create/update sessions are a bit cryptic
- Debugging is a bit harder (constant need to use get_decoded() and need to use SessionStore to change session_data on the fly)
Conversely, django.contrib.sessions.backends.cached_db does not store signed text, instead decoded object is directly written to cache;
So my thinking is that this was (probably?) done because:
- To make implementations consistent between backends
- Allow serialization methods other than JSON possible (hence all the pickling warnings in docs)
- JSONB columns did not exist back then / was not widely adopted
So right now, I’m planning to simplify things a little bit by using a JSONB column for session_data and dropping signing stuff entirely by making encode() and decode()no-op methods. I already override sessions in my projects to associate sessions with users anyway so it’s not a big hassle for me.
A gist of how that would work:
class MySession(AbstractBaseSession):
session_data = models.JSONField()
class SessionStore(DBStore):
@classmethod
def get_model_class(cls) -> type[AbstractBaseSession]:
return MySession
def decode(self, data: dict[str, Any]) -> dict[str, Any]:
return data
def encode(self, data: dict[str, Any]) -> dict[str, Any]:
return data
I haven’t seen anything similar to this being done in the wild, so I wanted to ask if I’m assuming or doing something wrong?