Backend de Autenticación LDAP para Django
Django es un web framework basado en python, con muchas bondades(que no voy a detallar en este post), y que , particularmente posee un sistema de autenticación muy flexible, el cual nos permite autenticar contra una base de datos por defecto, pero como sabemos, nuestra fuente de autenticacion no suele ser siempre una base de datos.
En ese caso, necesitamos nuestra propio backend para poder autenticar contra esa fuente, Django nos permite escribir nuestro propio backend de autenticacion, de forma que podamos autenticar nuestros usuarios con nuestra fuente de autenticacion ya existente.
Nosotros podriamos, por ejemplo, tener un servidor LDAP , que almacene a nuestros usuarios y sus passwords, asi que podriamos usarlo para autenticar en nuestra aplicacion Django. Basicamente, un backend de autenticacion para Django consta de una clase que implementa dos metodos, get_user(user_id), el cual devuelve un objeto User de Django, y authenticate(**credentials), en el cual debemos verificar el usuario con su password, y retornar un objeto User de Django.
Lo primero que debemos hacer es definir nuestro nuevo backend de autenticacion en settings.py, de forma que Django lo use:
AUTHENTICATION_BACKENDS = ( 'proyecto.utils.ldapauthbackend.LDAPBackend', 'django.contrib.auth.backends.ModelBackend', );
Inplementando todo esto, nos queda la siguente clase:
import ldap
from django.contrib.auth.models import User
class LDAPBackend:
#Metodo base de autenticacion
def authenticate(self, username=None, password=None):
#base de nuestro arbol ldap
AUTH_LDAP_BASE="dc=gerardo,dc=com,dc=ve"
AUTH_LDAP_BASE="dc=gerardo,dc=com,dc=ve"
AUTH_LDAP_SERVER = "el.servidor.ldap"
#si ambos base_user y base_pass son vacios,
#se realiza acceso anonimo al arbol ldap
AUTH_LDAP_BASE_USER = ""
AUTH_LDAP_BASE_PASS = ""
base = AUTH_LDAP_BASE
scope = ldap.SCOPE_SUBTREE
#Filtro de busqueda en nuestro arbol ldap
filter = "(&(objectclass=person) (uid=%s))" % username
ret = ['dn']
# Autenticamos el usuario base
try:
l = ldap.open(AUTH_LDAP_SERVER)
l.protocol_version = ldap.VERSION3
l.simple_bind_s(AUTH_LDAP_BASE_USER,AUTH_LDAP_BASE_PASS)
except ldap.LDAPError:
return None
try:
result_id = l.search(base, scope, filter, ret)
result_type, result_data = l.result(result_id, 0)
# Si el usuario no existe, falla.
if (len(result_data) != 1):
return None
# Autenticar con DN de usuario
l.simple_bind_s(result_data[0][0],password)
try:
user = User.objects.get(username__exact=username)
except:
#Este fragmento es importante, aun cuando autenticamos
#contra un servidor ldap, necesitamos crear un usuario
#en la bd de django, pero en este caso, creamos un
#password temporal, de forma que no pueda usar ese
#objeto para autenticarse posteriormente, sino nuestro
#Servidor LDAP
from random import choice
import string
temp_pass = ""
for i in range(8):
temp_pass = temp_pass + choice(string.letters)
user = User.objects.create_user(username,username + '@gerardo.com.ve',temp_pass)
user.is_staff = False
user.save()
return user
except ldap.INVALID_CREDENTIALS:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
En este caso, he usado python-ldap, el cual esta en los repositorios de Debian. La implementación de este backend con ldaptor , la cual es una libreria python nativa para LDAP, resulta trivial de igual forma.
-
gerardo
-
Jesús Gómez


