Django管理员不使用自定义身份验证后端

时间:2016-05-06 11:07:09

标签: python django authentication

我有自定义用户模型和身份验证后端。 当我使用shell时,身份验证功能正常,但是当涉及到管理站点登录时,它就无法正常工作。

代码来自paper

settings.py

# Authentication
AUTH_USER_MODEL = 'BBUser.UserInfo'
AUTHENTICATION_BACKENDS = [
    'BBUser.models.AuthBackend',
    'BBUser.models.AdminAuthBackend',
]

models.py

class UserInfo(AbstractBaseUser, PermissionsMixin):
    openid = models.CharField(max_length=50, null=False, unique=True)
    nickname = models.CharField(max_length=30, null=True)
    ...

    USERNAME_FIELD = 'openid'
    REQUIRED_FIELDS = []
    ...

    objects = UserManager()


class AdminAuthBackend(object):
    def authenticate(self, openid=None, password=None):
        print "custom auth"
        login_valid = ('100' == openid)
        pwd_valid = ('tobeno.2' == password)
        if login_valid and pwd_valid:
            try:
                user = UserInfo.objects.get(openid=openid)
            except UserInfo.DoesNotExist:
                user = UserInfo(openid=openid, password='get from .py')
                user.is_staff = True
                user.is_superuser = True
                user.save()
            return user
        return None

    def get_user(self, user_id):
        try:
            return UserInfo.objects.get(pk=user_id)
        except UserInfo.DoesNotExist:
            return None

因为我在AdminAuthBackend.authenticate()中添加了print,所以我知道它何时被执行。

当我从shell调用authenticate()时,在管理页面中调用自定义身份验证方法,而不是。

感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

我自己找到了答案。

在深入研究Django的源代码后,我发现django.contrib.auth.forms中的这个片段处理来自管理站点登录表单的帖子请求:

def clean(self):
    username = self.cleaned_data.get('username')
    password = self.cleaned_data.get('password')

    if username and password:
        self.user_cache = authenticate(username=username,
                                       password=password)
        if self.user_cache is None:
            raise forms.ValidationError(
                self.error_messages['invalid_login'],
                code='invalid_login',
                params={'username': self.username_field.verbose_name},
            )
        else:
            self.confirm_login_allowed(self.user_cache)

    return self.cleaned_data

请注意,虽然它使用auth.authentication来处理登录操作,但它实际上解析了固定字段usernamepassword,这意味着默认的管理站点登录表单忽略了您自己的AuthenticationBackends。 / p>

要解决此问题,我需要为管理站点实现自己的登录表单。

答案 1 :(得分:1)

这是我的解决方案..希望它会帮助某人:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend' #add this line
    'your auth backend'
]

保留默认的 django.contrib.auth.backends.ModelBackend 类以确保 django 管理使用的默认用户名/密码验证工作流。然后添加您的自定义身份验证后端类,以便您进行更改。

答案 2 :(得分:0)

使用带有电子邮件身份验证的自定义模型时,我遇到了完全相同的问题。我设法通过创建一个新的后端类来解决此问题。 据我了解,django遍历了应用程序中定义的所有后端,检查是否有确切的导入参数。

在这种情况下,也许类似的事情会起作用

class EmailAdminBackend(ModelBackend):
def authenticate(self, request, username=None, password=None):
    UserModel = get_user_model()
    try:
        # Check if the user exists in Django's database
        user = UserModel.objects.get(openid=username)
    except :
        return None
    if user.check_password(password):
        return user
    return None