Ed Crewe - Oct 2019
This package provides a sessions implementation and decorator class for views to allow for forms to maintain state without using cookies by posting the session id between forms, or via urls.
Django requires cookies to maintain session, and hence for authorisation.
This package is designed to cater for anonymous user session maintenance, without cookies.
WARNING : There are security issues with this, since it is not possible to use CSRF protection without session Cookies to maintain a separate token from that passed via the URL or form posts.
However there are cases when forms are used on a public site, where setting cookies is not desirable (due to privacy legislation <http://www.ico.gov.uk/>
_), since technically they are not required for anonymous users to respond to forms.
So if used, may necessitate requesting permission to set cookies, from the user.
Hence this package was devised to allow django to deliver multipage forms, without using cookies.
To ameliorate the security implications, a whitelist of allowed domains, can be set in the configuration.
Usage can also be restricted to a particular URL.
As another safety measure, handling of GET requests can be turned off, so that the encrypted session id is not present in any URLs.
Please NOTE: It is not advisable to use this package without some form of the above restrictions being in place.
For the purposes of using both cookie based and cookieless sessions together, there is a custom cookieless_signal(sender=request, created) and a 'no_cookies' flag when cookieless sessions are saved.
Both cater for hooking up custom code for handling these less secure sessions.
The package provides a decorator utility to turn off cookie setting for particular views (which also sets the csrf_exempt flag).
The package also handles the case of session handling for anonymous users with cookies disabled in the browser.
You can decorate views to prevent them setting cookies, whilst still retaining the use of Sessions. Usually this is easiest done in the urls.py of your core application ...
from cookieless.decorators import no_cookies
urlpatterns = [ ... path('somewhere/index', no_cookies(views.home)), ... re_path(r'^somewhere/page/(\d{1,6})$', no_cookies(views.page)), ...]
Note that if a number of browser tabs are open on to a site with cookieless, they will each maintain a completely separate session, since without cookies the session is tied to the session posted from the pages accessed, not the client as a whole.
In cases where this is not the desired behaviour, then it can be reduced by using URL rewriting to make any links to open other windows pass session across. However of course this also means that potentially a session can be shared across browsers, too.
To install add the package via pip or other build tool, e.g. bin/pip install django-cookieless
Then replace the standard Session in the middleware settings:
MIDDLEWARE = ( ... 'django.middleware.gzip.GZipMiddleware', ... 'django.middleware.common.CommonMiddleware', ... 'django.middleware.transaction.TransactionMiddleware', ... # 'django.contrib.sessions.middleware.SessionMiddleware', ... 'cookieless.middleware.CookielessSessionMiddleware', ...)
The following settings control its behaviour:
(see the example settings file)
COOKIELESS['REWRITE'] = True
COOKIELESS['USE_GET'] = True
COOKIELESS['CLIENT_ID'] = True
COOKIELESS['HOSTS'] = ['localhost', ]
COOKIELESS['NO_COOKIE_PERSIST'] = True
COOKIELESS['URL_SPECIFIC'] = True
COOKIELESS['DELETE_COOKIES'] = False
The test suite sets up a simple application to test cookies manually, and to run the functional tests against.
To run the tests, you may want to install from src (or your branch):
bin/pip install -e git+https://github.com/edcrewe/django-cookieless#egg=django-cookieless
Then run via:
bin/django-admin.py or manage.py test cookieless.tests --settings=cookieless.tests.settings
(The package was changed from a namespace package due to the issue with pip not installing the init for running tests when it does a nspkg.pth file instead)
Because the django test browser has some session implementation specific mocking, it fails to work if used directly against cookieless, so to stop it breaking other tests cookieless checks to see if the django admin command has been called with the 'test' argument and sets settings.TESTING = True, and doesnt decorate with no_cookies if so.
To override this automatic disabling setting, just add TESTING = False, to your test settings.
[Ed Crewe]
[Ed Crewe]
[Chris Bailey]
[Ed Crewe]
Turn off cookieless for django test browser - since its hard coded to use dummy sessions if an alternative session provider is in use - otherwise cookieless could break other packages tests
Add server name switch to re-enable test browser for cookieless functional tests
Change anon user switch to be NO_COOKIE_PERSIST - ie. never use cookie originated sessions - move to process_response
Make session use cookieless post / get first over cookies, if present
Delete request cookies if found in response
Refactor settings to a dictionary
Add some tests
Move fix for non-unicode key to the decrypt method
[Ed Crewe]
Add COOKIELESS_ANON_ONLY setting to not use cookieless if a user is authorised
Update example settings
Add test suite
Don't assume request META keys exist so OK with test client etc.
Fix session decrypt with wrong secret - generates non-unicode key bug rather than new session
Add SPECIFIC_URL option for extra security for sessions
[Ed Crewe]
Django snippets - http://djangosnippets.org/snippets/1540/ Basis of middleware
Add simple crypt of sessionid when used in HTML
Call standard contrib.sessions.Session if not decorated as no_cookies
Add CSRF exempt decorator too to ensure cookie not set by that
Add templatetags for users who prefer manual adding of session ids
Add settings options to configure level of security applied, e.g. whitelist of referers, no URL rewriting etc.
[Ed Crewe, julio carlos and Ivscar (snippet), Paul Chakravarti (xteacrypt)]
Version | Tag | Published |
---|---|---|
1.2 | 3yrs ago | |
1.1 | 3yrs ago | |
1.0 | 8yrs ago | |
0.9 | 9yrs ago |