24 июня 2009 г.

Ldap авторизация в Django

Вопрос ldap авторизации в Python довольно хорошо рассмотрен. Теперь разберем, как привязать эту авторизацию к Django.
Первый вариант в рамках компании будет регистрация на сайте с django путем авторизации в ldap.
Другой вариант - полная интеграция авторизации ldap в джанго, но тогда все преимущества групп и контроля доступа теряются, если только не получать эту дополнительную информацию от ldap или других источников.
Третий, наиболее гибкий вариант. Отсутствие регистрации. Логиним пользователя - ищем его профиль в auth у Django - если его нет, создаем, если есть - то используем найденный профиль (если пароль в Django не совпадает с ldap паролем - обновляем его).

Давайте пойдем по третьему пути.

Для начала подготавливаем Django. У нас будет расширенный стандартный Django User, так как после авторизации пользователя в ldap мы еще получим его данные с корпоративной базы mssql.

Устанавливаем python-ldap:
  1. $ sudo apt-get install python-ldap  

Прописываем в settings.py:
  1. LDAP_DOMAIN='mydomain.com'    
  2. LDAP_SERVER='ldaps://%s' % LDAP_DOMAIN #SSL connection  

Правим файл auth.py:
  1. # -*- coding: utf-8 -*-  
  2.   
  3. from django.conf import settings  
  4. from django.contrib.auth.backends import ModelBackend  
  5. from django.core.exceptions import ImproperlyConfigured  
  6. from django.db.models import get_model  
  7. from social.models import CustomUser   
  8.   
  9. class CustomUserModelBackend(ModelBackend):  
  10.       
  11.     def get_local_user(self, email, password=None):  
  12.               
  13.         try:  
  14.             user = self.user_class.objects.get(email=email.lower())  
  15.             if user.check_password(password):  
  16.                 return user  
  17.             else:  
  18.                 self.exist_user=user#save user for refresh local data  
  19.         except self.user_class.DoesNotExist:  
  20.             return None  
  21.   
  22.     def get_ldap_refresh_create_user(self, username=None, password=None):  
  23.         import ldap, sys  
  24.           
  25.         #create new local user  
  26.         if '@' in username:  
  27.             #user@domain  
  28.             LDAP_USERNAME=username  
  29.             username=username.split('@')[0]  
  30.         else:  
  31.             #user  
  32.             LDAP_USERNAME='%s@%s' % (username, settings.LDAP_DOMAIN)  
  33.           
  34.         LDAP_PASSWORD=password  
  35.   
  36.         try:    
  37.              # build a client    
  38.              ldap_client = ldap.initialize(settings.LDAP_SERVER)    
  39.              # perform a synchronous bind    
  40.              ldap_client.simple_bind_s(LDAP_USERNAME, LDAP_PASSWORD)  
  41.         except ldap.INVALID_CREDENTIALS, e:    
  42.              return False  
  43.         except ldap.SERVER_DOWN, e:    
  44.              return False#@todo raise Validation error  
  45.           
  46.         #lpad auth succes:  
  47.           
  48.         #try to get local user  
  49.         user=self.get_local_user(LDAP_USERNAME, password)  
  50.           
  51.         if user:#if we check user in localbase  
  52.             return user  
  53.         else:#else create new or refresh old pass   
  54.             if hasattr(self'exist_user'):  
  55.                 #refresh local auth data from ldap in case of change pass  
  56.                 self.exist_user.set_password(password)  
  57.                 self.exist_user.save()#write new pass  
  58.                 user=self.exist_user  
  59.             else:  
  60.                 user=CustomUser.objects.create_user(username,LDAP_USERNAME,password)  
  61.                   
  62.             return user  
  63.       
  64.     def updape_user_info(self, user):  
  65.         pass  
  66.            
  67.     def authenticate(self, username=None, password=None):  
  68.         #try to auth with ldap  
  69.         #and refresh user data in success or create new one if user does not exist  
  70.         user=self.get_ldap_refresh_create_user(username, password)  
  71.         if user:  
  72.             self.updape_user_info(user)#get data from mssql  
  73.             return user  
  74.         else:  
  75.           return None# error ldap auth  
  76.           
  77.     def get_user(self, user_id):  
  78.         try:  
  79.             return self.user_class.objects.get(pk=user_id)  
  80.         except self.user_class.DoesNotExist:  
  81.             return None  
  82.  
  83.     @property  
  84.     def user_class(self):  
  85.         if not hasattr(self'_user_class'):  
  86.             #self._user_class = get_model(*settings.CUSTOM_USER_MODEL.split('.', 3))  
  87.             self._user_class = CustomUser  
  88.             if not self._user_class:  
  89.                 raise ImproperlyConfigured('Could not get custom user model')  
  90.         return self._user_class  


Функция updape_user_info на самостоятельное написание, она должна дописывать необходимую расширенную информацию.

ps. прозрачная авторизация в принципе возможна, но только с IE, можете попробовать.

Комментариев нет:

Отправить комментарий