Reputation: 1140
I want to put basic HTTP authentication somewhere in my code if a certain condition is met. The condition is a request parameter. To simplify, let's say I want it in a Django view.
I know how to do it in PHP. This is the chunk of code which does exactly what I want:
if (isset($_REQUEST['key']) && $_REQUEST['key'] === 'value') {
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
}
I can put this chunk of code anywhere in my PHP script and when execution hits those lines, authentication will be requested. If authentication fails, script execution will stop and a 401 Unauthorized header will be sent with the specified message. This is what I want in Python/Django. Here is a chunk of code, help me fill it in:
def some_view(request):
if request.REQUEST.get('key') == 'value':
# FILL ME IN
What I want:
What I DON'T want:
Upvotes: 1
Views: 1466
Reputation: 53699
from django.http import HttpResponse
def some_view(request):
if request.REQUEST.get('key') == 'value':
if not request.user.is_authenticated():
response = HttpResponse('Text to send if user hits Cancel button', status=401)
response['WWW-Authenticate'] = 'Basic realm="My Realm'
return response
...
This will return a 401
status code, but requires you to provide your own content/template. If it is acceptable for you to return a 403
status code, you can use the built-in PermissionDenied
exception that returns a 403 page based on your '403.html' template:
from django.core.exceptions import PermissionDenied
def some_view(request):
if request.REQUEST.get('key') == 'value':
if not request.user.is_authenticated():
raise PermissionDenied
...
EDIT:
To implement HTTP Basic Authentication, you have to set up your webserver (Apache, nginx, whatever you're using) to handle this. You should check your webserver's documentation on how to do this.
Django implements a RemoteUserBackend
to allow users to login using basic authentication, but this uses the same user model as the normal ModelBackend
, so these are not separate. Luckily, the middleware and the backend are quite simple. The webserver will deny any request with invalid credentials, so any time the 'REMOTE_USER'
header (or whatever header value you use) is set, the user is properly authenticated. This header will be available in request.META
, so to check if a user is authenticated using Basic Authentication, you can use this code:
from django.http import HttpResponse
def some_view(request):
if request.REQUEST.get('key') == 'value':
if request.META.get('REMOTE_USER', None):
do_something()
else:
response = HttpResponse('Text to send if user hits Cancel button', status=401)
response['WWW-Authenticate'] = 'Basic realm="My Realm'
return response
...
Upvotes: 2
Reputation: 6005
I'd use a mixin with django's class based views for this
class AuthenticationMixin(object):
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponse('text, test, text', status=401)
return super(AuthenticationMixin, self).dispatch(request, *args, **kwargs)
You would then use this in a view as follows
class MyView(AuthenticationMixin, DetailView):
.
.
.
If there is a view that you don't want to use authentication on all you need to do is not sub-class the authentication mixin in the class declaration
class MyUnauthenticatedView(DetailView):
.
.
.
Upvotes: 1