СУЩНОСТЬ
Как использовать пользовательскую модель пользователя и собственный сервер аутентификации (чтобы разрешить аутентификацию по электронной почте/паролю) с помощью Django + MongoEngine? (Является ли обычным бэкэндом, даже необходимым для этого?... т.е. использовать электронную почту для имени пользователя при аутентификации с помощью MongoEngine.)
Есть ли какая-либо документация с прямолинейным (и полным!) примером использования пользовательского объекта пользователя при использовании Mongo в качестве основного хранилища данных при аутентификации в Django? (Postgres имеет такие четкие и более всеобъемлющие документы...)
ДЕТАЛЬ
MongoEngine, по-видимому, дает вам только два варианта аутентификации - "Классический" (например, "mongoengine.django.auth.MongoEngineBackend" )... ИЛИ... "Пользовательская модель пользователя" (также известный как "django. contrib.auth.backends.ModelBackend ') - оба из которых более или менее кратко изложены в Николасе Кортоте, отвечая на другой вопрос здесь:
Python-Social-Auth не работает с mongoEngine (Django)
Оба этих метода аутентификации дают вам доступ к методу authenticate(), аналогичному классу Django AbstractBaseUser, - методу, который полагается на функцию check_password. Тем не менее, в тот момент, когда вы используете так называемую "пользовательскую модель пользователя", аутентификацию (как указано в приведенной выше ссылке)... и затем соединяйте ее с пользовательским бэкэнд (для использования электронных писем для имен пользователей)... вы возникают проблемы из-за отсутствия доступа к типичной функции authenticate().
Например, так...
accounts.models.py
# ...with postgres, I'd subclass AbstractBaseUser...but with Mongo...(?) from django.conf import settings from mongoengine.fields import EmailField, BooleanField
from mongoengine.django.auth import User class MyUser(User): email = EmailField(max_length=254, unique=True) is_active = BooleanField(default=True) is_admin = BooleanField(default=False) USERNAME_FIELD = 'email' REQUIRED_FIELDS = '' ...
my_custom_backend.py
# ...is a custom backend even necessary to use email for authentication instead of username? from django.conf import settings from django.contrib.auth.models import check_password #from mongoengine.django.auth import check_password #from django.contrib.auth.hashers import check_password from models import MyUser class EmailAuthBackend(object): def authenticate(self, email=None, password=None): # ...uh oh, since I'm NOT using one of the usual backends with a pre-existing authenticate() # method, there ain't a native check_password() function available. Means I have to hash the # password, etc.
Итак, похоже, я обязан написать свою собственную функцию check_password. Чтобы получить всю доброту, присущую классу AbstractBaseUser, обычно найденному с помощью проверки PostgreSQL, мне пришлось бы полностью раздуть мою пользовательскую модель пользователя, которая кажется взломанной и не может быть очень СУХОЙ.
Неужели я совершенно запутался?... т.е. действительно ли совершенно необязательно использовать пользовательский бэкэнд, если я хочу использовать электронные письма вместо имен пользователей для аутентификации при использовании MongoEngine?
Я чувствую, что у меня может быть фундаментальное непонимание того, как Django работает с MongoEngine в отношении аутентификации, и в отношении того, как я смоделировал и вызвал пользовательский объект пользователя/мое конкретное подклассирование объекта пользователя MongoEngine во время этого процесса...
Потому что - как это сейчас - я получаю объект 'AnonymousUser', в браузере отсутствует сообщение об ошибке "backend" . Я также отметил, что эта проблема иногда возникает по непредвиденным причинам, а именно: возможно, метод authenticate() ожидает хешированный пароль или потому, что логин (электронная почта) слишком длинный...? Для большего количества случаев, когда это последнее обстоятельство может иметь место, см.:
Объект регистрации Django 'AnonymousUser' не имеет атрибута 'backend'
settings.py
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin', 'mongoengine.django.mongo_auth', 'accounts', ) AUTHENTICATION_BACKENDS = ( 'mongoengine.django.auth.MongoEngineBackend', #'accounts.my_custom_backend.EmailAuthBackend', #'django.contrib.auth.backends.ModelBackend', ) AUTH_USER_MODEL = 'mongo_auth.MongoUser' MONGOENGINE_USER_DOCUMENT = 'accounts.models.User'
accounts.views.py
from django.contrib.auth import login as django_login from my_custom_backend import EmailAuthBackend from forms import AuthenticationForm def login(request): form = AuthenticationForm(data=request.POST) if form.is_valid(): try: backend = EmailAuthBackend() user = backend.authenticate(email=request.POST['email'], password=request.POST['password']) django_login(request, user) return redirect('/') except DoesNotExist: return HttpResponse('user does not exist') else: form = AuthenticationForm() return render_to_response('accounts/login.html', { 'form': form }, context_instance=RequestContext(request))