Home

RestrictMiddleware


Here’s another one that I’ve yanked out of a project. I call it RestrictMiddlware and it is a real simple, and really easily bypassed “security” mechanism. Like most security, it’s just security theater, but some clients make it so hard to enable true security that you’ve got to resort to this type of stuff.

As a warning, I’d really emphasize that you shouldn’t ever use this type of access restriction on any site that contains truly secure, private, or sensitive material. Use strong user logins or better.

This is the RestrictMiddleware and you just pop it into your Django settings.py under the MIDDLEWARE_CLASSES section. By default, this middleware is going to deny access to every request, so a little bit of configuration is required. This is all laid out in much detail in the documentation of this middleware; the following items must be added to your settings.py for the middleware to pick them up.

  • RESTRICT\_IP\_WHITELIST: a list or tuple of strings representing IP addresses
  • RESTRICT\_REFERRER\_WHITELIST: a list or tuple of strings to be searched as substrings in a request’s HTTP_REFERRER
  • RESTRICT\_GET\_CODE: a dictionary of key/value pairs which, if specified, will be checked for complete equality with a client’s GET paramters.
  • RESTRICT\_COOKIE\_NAME: a string representing the name of a cookie that will be checked at the beginning of the process and will be set if any of the tests pass.
  • RESTRICT\_ACCESS\_DENIED\_MESSAGE: a string that will be displayed to the user in the event of no tests being passed.

Some examples:

RESTRICT_IP_WHITELIST = (
    '127.0.0.1',
    '24.39.293.222',
    '24.39.292.222',
)

RESTRICT_COOKIE_NAME = 'my_auth'

RESTRICT_GET_CODE = { 'i': 'ae723bff82e8f', }

RESTRICT_ACCESS_DENIED_MESSAGE = 'You're not authorized. Get out!'

This middleware applies up to four tests on a request. If any of them pass, a session variable, and the request is passed on. In the documentation and in the examples above, the term cookie is still used. This isn’t an accurate representation of what actually takes place. Django maintains a single cookie in a user’s browser with a unique session hash. When a client is marked as safe, a special session variable is flipped to “true” on the server side. This is a little bit “safer” than what I imply in the code.

As you might’ve guessed, the first test is to see if the session variable has already been set. The second is if the request’s IP is in the IP white list. The third is if the referrer is in the white listed referrer list. The final test are the “get codes”. If a dictionary of “get codes” is supplied, this test only passes if all of the codes are present in the request and their values match exactly.

As I mentioned before, only one of these tests must evaluate to true for a request to be considered valid and the client marked as safe (session variable set). A future improvement might be to allow a user configure which tests must pass (or all of them) before a request is considered valid. Another might be to ditch the session variable altogether and validate every single request.