【问题标题】:MongoEngine -- how to custom User model / custom backend for authenticate()MongoEngine -- 如何为 authenticate() 自定义用户模型/自定义后端
【发布时间】:2014-01-31 02:17:22
【问题描述】:

摘要

如何在 Django + MongoEngine 中使用自定义用户模型自定义身份验证后端(以允许电子邮件/密码身份验证)?(甚至是自定义后端有必要吗?...即,在使用 MongoEngine 进行身份验证时使用电子邮件作为用户名。)

是否有任何文档包含使用 自定义用户对象同时使用 Mongo 作为主数据存储的直接(且完整!)示例authenticating 在 Django 中?(Postgres 有这样更清晰、更全面的文档...)


详情

MongoEngine 似乎只为您提供两种身份验证方式——“经典”(又名 'mongoengine.django.auth.MongoEngineBackend')方式......或者......“自定义用户”模型”(又名 'django.contrib.auth.backends.ModelBackend')方式——在 Nicolas Cortot 对不同问题的回答中或多或少地简洁地概述了这两种方式:

Python-Social-Auth fails with mongoEngine (Django)

这两种身份验证技术都可以让您访问类似于 Django 的 AbstractBaseUser 类的 authenticate() 方法——该方法依赖于 check_password 函数。但是,在您使用所谓的“自定义用户模型”身份验证风格(如上面的链接中所述)的那一刻......并且然后将其与自定义后端配对(以便使用电子邮件对于用户名)...由于无法访问典型的 authenticate() 函数,您会遇到麻烦。

例如,像这样……

accounts.models.py


# ...使用 postgres,我将继承 AbstractBaseUser...但使用 Mongo...(?) 从 django.conf 导入设置 从 mongoengine.fields 导入 EmailField, BooleanField
从 mongoengine.django.auth 导入用户 类我的用户(用户): email = EmailField(max_length=254, unique=True) is_active = BooleanField(默认=真) is_admin = BooleanField(默认=假) USERNAME_FIELD = '电子邮件' REQUIRED_FIELDS = '' ...

my_custom_backend.py

# ...是否需要自定义后端才能使用电子邮件而不是用户名进行身份验证? 从 django.conf 导入设置 从 django.contrib.auth.models 导入 check_password #from mongoengine.django.auth 导入 check_password #from django.contrib.auth.hashers 导入 check_password 从模型导入 MyUser 类 EmailAuthBackend(对象): def 身份验证(自我,电子邮件=无,密码=无): # ...呃哦,因为我没有使用带有预先存在的 authenticate() 的常用后端之一 # 方法,没有可用的本机 check_password() 函数。意味着我必须散列 #密码等

所以,貌似,我不得不编写自己的 check_password 函数。为了获得通常在 PostgreSQL 身份验证中发现的 AbstractBaseUser 类固有的所有优点,我必须完全扩展我的自定义用户模型,这看起来很老套,而且不太干。 p>

我在这里完全糊涂了吗? ...即,如果我想在使用 MongoEngine 时使用电子邮件而不是用户名进行身份验证,是否真的完全不需要使用自定义后端?

我觉得我可能对 Django 在身份验证方面如何与 MongoEngine 一起工作,以及我在该过程中如何建模和调用自定义用户对象/我的 MongoEngine 用户对象的特定子类存在根本性的误解。 ..

因为 - 就像现在一样 - 我在浏览器中收到“'AnonymousUser' 对象没有属性 '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', '帐户', ) 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

从 django.contrib.auth 导入登录为 django_login 从 my_custom_backend 导入 EmailAuthBackend 从表单导入 AuthenticationForm def 登录(请求): 表单 = AuthenticationForm(data=request.POST) 如果 form.is_valid(): 尝试: 后端 = EmailAuthBackend() 用户 = backend.authenticate(email=request.POST['email'], password=request.POST['password']) django_login(请求,用户) 返回重定向('/') 除了不存在: return HttpResponse('用户不存在') 别的: 表单 = AuthenticationForm() return render_to_response('accounts/login.html', {“形式”:形式}, context_instance=RequestContext(请求))

【问题讨论】:

    标签: django authentication mongoengine custom-backend


    【解决方案1】:

    好吧,看起来最好的做法是不要将 Django 的用户交给 Mongo 进行身份验证...通过 Twitter 获得了这个金块:

    @blogblimp我的简短回答:尽量避免用 MongoDB 替换 Django 用户模型。你失去了 Django 的所有力量,失去了 MongoDB 的速度。 说真的,用户与一切都相关,而 MongoDB 不是关系型的。

    — Daniel Roy Greenfeld (@pydanny) January 20, 2014


    所以:我将只使用 PostgreSQL 进行身份验证,使用 Mongo 进行其他对象。这意味着在 Django 设置中命名/连接到两个数据库。回想起来,我认为道德是:永远不要仅仅因为 Mongo 很酷而使用它。 Mongo 在 Django 世界里仍然是二等公民。

    【讨论】:

      【解决方案2】:

      也许我来晚了,但我可以使用 mongoengine User + django authenticate 来完成电子邮件身份验证的任务,这是我的工作方式:

      from django.contrib.auth import authenticate, login as do_login, logout as do_logout
      
      def login(request):
      
          data = extractDataFromPost(request)
          email = data["email"]
          password = data["password"]
      
          try: 
              user = User.objects.get(username=email)
              if user.check_password(password):
                  user.backend = 'mongoengine.django.auth.MongoEngineBackend'
                  user = authenticate(username=email, password=password)
                  do_login(request, user)
                  request.session.set_expiry(3600000) # 1 hour timeout
                  return jsonResponse(serializeUser(user)) 
              else:
                  result = {'error':True, 'message':'Invalid credentials'}
                  return jsonResponse(result) 
          except User.DoesNotExist:
              result = {'error':True, 'message':'Invalid credentials'}
              return jsonResponse(result)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-11
        • 1970-01-01
        • 2011-10-22
        相关资源
        最近更新 更多