I have a Django application which liberally uses django.contrib.auth.decorators.login_required() and also django.views.decorators.http.require_http_methods(). The former is a decorator which checks whether the current user is logged in, and redirects them (with code 302, IIRC) to the login page if not logged in. The latter is a decorator which examines the request method, and returns 405 (method not implemented) if the method isn’t in the passed-in list. So, as an example, a view function might look like:
@require_http_methods(["GET", "POST", "DELETE"])
@login_required
def my_view(request):
...
Here’s the problem: Many of these views do internal permission checks which return 403 (forbidden) if the user lacks sufficient permissions for the resource. According to my research, this is bad, because 403 needs to happen before examining whether the method is correct. However, without login_required(), I would have to open-code the user checks as well in my views.
Has anybody else experienced this? Is there a correct answer? I know it’s cheating, but is it unacceptable to check methods, then do the login redirect, then finally check user permissions, or do I need to restructure these views?
I’m not really sure about the ‘correctness’ of your order, but for any sort of complex view permission scheme I would highly recommend writing your own custom middleware to take care of view authentication / permissions. Rather than decorate every view with
@login_requiredI always just take care of it in my own middleware.You can also write your own view decorator(s) (which may or may not take arguments) and get exactly the behavior you want for different views.