我有自定义用户模型和身份验证后端。 当我使用shell时,身份验证功能正常,但是当涉及到管理站点登录时,它就无法正常工作。
代码来自paper
# Authentication
AUTH_USER_MODEL = 'BBUser.UserInfo'
AUTHENTICATION_BACKENDS = [
'BBUser.models.AuthBackend',
'BBUser.models.AdminAuthBackend',
]
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()
时,在管理页面中调用自定义身份验证方法,而不是。
感谢任何帮助。
答案 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
来处理登录操作,但它实际上解析了固定字段username
和password
,这意味着默认的管理站点登录表单忽略了您自己的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