How does Django put session into your browsers/cookies
As a proud web developer, I definitely know about cookies and sessions.
- Cookie is used to pass data between browser and server
- Session is the data stored on server side
That sounds about right. So when I logged into a Django site, pass the authentication then Django will have something remembered so I don’t have to login for every request.
But how exactly that worked?
Django authentication system is based on session.
In Django authentication middleware 1:
The middleware first assert there’s session avaible on request object, but what actually uses sessions is in the get_user function in auth module:
As I already know, the session is what Django useing on server side, basic HTTP protocal is stateless, most web server frameworks implemnt the session mechanism to make the request infomation persistable. From the authentication code above, all magic happend in request.session. It’s an object of SessionStore, which is the class in django to manage how the session data is saved, based on different settings, Django support save the session data in different places. For the sake of focusing on Django session and browser, I’ll view it as a blackbox 2. The session object is added to request in Django’s SessionMiddleware
And look at the above code closer, the session object is actually looked up by session key, getting from cookies. Problem solved! Django will put the key of session into cookies, then it can be reused across requests.
In order to put the session key into cookies, in the process_response part of Django SessionMiddleware, after some cleanup work, it finally set the cookie in the end.
# Save the session data and refresh the client cookie.
Unlike session, cookies is a real HTTP standard, more details can be found in RFC 6265. Here we can go over the arguments of the set_cookie function and find out what can be controlled in Django’s session.
Cookie is key-value pairs, this is the name part of the session key in cookie
This is the actual value stored in cookie
max_age and expires
These two arguments are closely related, in cookie, they are “Max-Age” and “Expires” attributes. Both attributes control how long the data can stay in cookie, Max-Age is the seconds of the cookie liftime, Expires is the specific date when the cookie will expire.
Max-Age has a higher priority over exipres, if either of them exists, the cookie will be kept in browser until the end of its liftime, even after browser closed. If none of them are set, the cookie will be cleared after the session (this is the session of connection, not the server side session) closed, normally that means browser closed. As you might notice the two arguments are not read from settings directly, there’s a small part of logic to set them.
And the get_expire_at_browser_close method is basically controlled by settings.SESSION_EXPIRE_AT_BROWSER_CLOSE
This is the Domain attribute, it controls if the cookie can be used for the request.
When using cookie, the request host needs to match the domain attribute, or the domain attribe is suffix of the request host. For example, if the domain ise set to .x.com, the request from a.x.com will be considered match as well.
When set the cookie, this attribute also needs to match request host, for security reason cookie specified for unmatched domain will be rejected. Which means you can’t set cookie from your site to google.com.
Also, event not violate the match logic, most agent will reject domain set on public suffix like “com” or “co.uk”
This is the Path attribute, like the domain attribute, it limits the scope of the cookie can be used. Only cookie with matched path is valid.
This is the Secure attribute, if set to true, cookies will only be used in secure connection (normally means HTTPS). It’s default as False in Django settings, but it’s recommended to be set if you site has https.
1 All code taken from django source code on github (tag 1.9.5) ↩
2 There’s a session implementation called cookie based backend, which not only pass session key in cookies but also put all session data in cookies ↩