SUMMARY
How do I use a custom User model and a custom authentication backend (to allow for email / password authentication) with Django + MongoEngine? (自定义后端甚至是必需的吗?...即,在使用MongoEngine进行身份验证时使用电子邮件作为用户名 . )
Is there any documentation with a straight-forward (and complete!) example of using a custom user object while using Mongo as the primary datastore when authenticating in Django? (Postgres有更清晰,更全面的文档...)
DETAIL
MongoEngine似乎只给你两种版本的身份验证 - "Classic"(又名'mongoengine.django.auth.MongoEngineBackend ') way...OR...the 312455 (aka ' django.contrib.auth.backends.ModelBackend ') way--both of which more or less succinctly outlined in Nicolas Cortot'这里回答了另一个问题:
Python-Social-Auth fails with mongoEngine (Django)
这两种身份验证技术都允许您访问类似于Django的AbstractBaseUser类的authenticate()方法 - 一种依赖于check_password函数的方法 . 但是,一分钟你使用所谓的"Custom User Model"身份验证风格(如上面的链接所述)...然后将其与自定义后端配对(为了使用电子邮件用于用户名)...你遇到了麻烦无法访问典型的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函数 . 为了获得通常在PostgreSQL身份验证中找到的AbstractBaseUser类所固有的所有优点,我非常干 .
我在这里完全糊涂了吗? ...即,如果我想在使用MongoEngine时使用电子邮件而不是用户名进行身份验证,那么实际上完全没必要使用自定义后端吗?
我觉得我可能对Django在认证方面如何与MongoEngine一起工作有一个根本的误解,关于我如何在该过程中建模并调用自定义用户对象/我特定的MongoEngine用户对象的子类...
因为 - 就像现在一样 - 我在浏览器中收到“ 'AnonymousUser' object has no attribute 'backend' ”错误消息 . 我还注意到这个问题有时会出于意料之外的原因 - 即:authenticate()方法可能需要散列密码,或者因为登录(电子邮件)太长了......?对于后一种情况可能是这种情况的更多情况,请参阅:
Django Register Form 'AnonymousUser' object has no attribute '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))
2 回答
嗯,看起来最好的行动方案是不要将Django的用户移交给Mongo进行身份验证开始...通过Twitter获得这个金块:
@blogblimp我的简短回答:尽量避免用MongoDB替换Django用户模型 . 你失去了所有的Django权力并且失去了MongoDB 's speed. Seriously, user relates to everything and MongoDB isn' t关系 .
所以:我很酷 . Mongo仍然是Django世界的二等公民 .
也许我有点晚了,但我可以使用mongoengine用户django身份验证来完成电子邮件身份验证的任务,这是我的工作方式: