Répondre

8

Lorsque vous effectuez une demande d'authentification de base, vous ajoutez réellement des informations d'identification dans l'en-tête Authorization. Avant le transit, ces informations d'identification sont codées en base64, vous devez donc les décoder à la réception.

L'extrait de code suivant suppose qu'il n'y a qu'un seul nom d'utilisateur et mot de passe:

import base64 

def my_view(request): 
    auth_header = request.META.get('HTTP_AUTHORIZATION', '') 
    token_type, _, credentials = auth_header.partition(' ') 

    expected = base64.b64encode(b'username:password').decode() 

    if token_type != 'Basic' or credentials != expected: 
     return HttpResponse(status=401) 

    # Your authenticated code here: 
    ... 

Si vous souhaitez comparer au nom d'utilisateur et mot de passe d'un modèle User, essayez ce qui suit à la place:

def my_view(request): 
    auth_header = request.META.get('HTTP_AUTHORIZATION', '') 
    token_type, _, credentials = auth_header.partition(' ') 

    username, password = base64.b64decode(credentials).split(':') 
    try: 
     user = User.objects.get(username=username) 
    except User.DoesNotExist: 
     return HttpResponse(status=401) 

    password_valid = user.check_password(password) 

    if token_type != 'Basic' or not password_valid: 
     return HttpResponse(status=401) 

    # Your authenticated code here: 
    ... 

Veuillez noter que cette dernière version n'est pas extrêmement sécurisée. À première vue, je peux voir qu'il est vulnérable à timing attacks, par exemple.

+0

Oui, cela devrait fonctionner. Mais je pense que je suis sur la mauvaise voie si je le résous comme ça. J'ai des directives personnelles (pour moi). L'un est "Ne pas écrire le code source pour implémenter une sauvegarde" et le suivant "Ne pas écrire le code source pour implémenter l'authentification". Cela a été résolu par des gens plus talentueux auparavant et il y a déjà des implémentations qui ont été testées depuis plusieurs mois. Néanmoins merci pour cet extrait. Je pense que l'implémentation est beaucoup plus de code. – guettli

0

Vous pouvez essayer un décorateur personnalisé (comme cela semble être la méthode recommandée here et here) au lieu d'ajouter de nouveaux middleware:

my_app/decorators.py:

import base64 

from django.http import HttpResponse 
from django.contrib.auth import authenticate 
from django.conf import settings 


def basicauth(function): 
    def wrap(request, *args, **kwargs): 
     if 'HTTP_AUTHORIZATION' in request.META: 
      auth = request.META['HTTP_AUTHORIZATION'].split() 
      if len(auth) == 2: 
       if auth[0].lower() == "basic": 
        uname, passwd = base64.b64decode(auth[1]).split(':') 
        user = authenticate(username=uname, password=passwd) 
        if user is not None and user.is_active: 
         request.user = user 
         return view(request, *args, **kwargs) 

     response = HttpResponse() 
     response.status_code = 401 
     response['WWW-Authenticate'] = 'Basic realm="{}"'.format(
      settings.BASIC_AUTH_REALM 
     ) 
     return response 

Ensuite, utilisez ceci pour décorer votre vue:

from my_app.decorators import basicauth 


@basicauth 
def my_view(request): 
    ...